1*3ee47cadSRui Miguel Silva // SPDX-License-Identifier: GPL-2.0 2*3ee47cadSRui Miguel Silva /* 3*3ee47cadSRui Miguel Silva * Omnivision OV2680 CMOS Image Sensor driver 4*3ee47cadSRui Miguel Silva * 5*3ee47cadSRui Miguel Silva * Copyright (C) 2018 Linaro Ltd 6*3ee47cadSRui Miguel Silva * 7*3ee47cadSRui Miguel Silva * Based on OV5640 Sensor Driver 8*3ee47cadSRui Miguel Silva * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. 9*3ee47cadSRui Miguel Silva * Copyright (C) 2014-2017 Mentor Graphics Inc. 10*3ee47cadSRui Miguel Silva * 11*3ee47cadSRui Miguel Silva */ 12*3ee47cadSRui Miguel Silva 13*3ee47cadSRui Miguel Silva #include <asm/unaligned.h> 14*3ee47cadSRui Miguel Silva #include <linux/clk.h> 15*3ee47cadSRui Miguel Silva #include <linux/delay.h> 16*3ee47cadSRui Miguel Silva #include <linux/err.h> 17*3ee47cadSRui Miguel Silva #include <linux/i2c.h> 18*3ee47cadSRui Miguel Silva #include <linux/init.h> 19*3ee47cadSRui Miguel Silva #include <linux/module.h> 20*3ee47cadSRui Miguel Silva #include <linux/of_device.h> 21*3ee47cadSRui Miguel Silva #include <linux/gpio/consumer.h> 22*3ee47cadSRui Miguel Silva #include <linux/regulator/consumer.h> 23*3ee47cadSRui Miguel Silva 24*3ee47cadSRui Miguel Silva #include <media/v4l2-common.h> 25*3ee47cadSRui Miguel Silva #include <media/v4l2-ctrls.h> 26*3ee47cadSRui Miguel Silva #include <media/v4l2-subdev.h> 27*3ee47cadSRui Miguel Silva 28*3ee47cadSRui Miguel Silva #define OV2680_XVCLK_VALUE 24000000 29*3ee47cadSRui Miguel Silva 30*3ee47cadSRui Miguel Silva #define OV2680_CHIP_ID 0x2680 31*3ee47cadSRui Miguel Silva 32*3ee47cadSRui Miguel Silva #define OV2680_REG_STREAM_CTRL 0x0100 33*3ee47cadSRui Miguel Silva #define OV2680_REG_SOFT_RESET 0x0103 34*3ee47cadSRui Miguel Silva 35*3ee47cadSRui Miguel Silva #define OV2680_REG_CHIP_ID_HIGH 0x300a 36*3ee47cadSRui Miguel Silva #define OV2680_REG_CHIP_ID_LOW 0x300b 37*3ee47cadSRui Miguel Silva 38*3ee47cadSRui Miguel Silva #define OV2680_REG_R_MANUAL 0x3503 39*3ee47cadSRui Miguel Silva #define OV2680_REG_GAIN_PK 0x350a 40*3ee47cadSRui Miguel Silva #define OV2680_REG_EXPOSURE_PK_HIGH 0x3500 41*3ee47cadSRui Miguel Silva #define OV2680_REG_TIMING_HTS 0x380c 42*3ee47cadSRui Miguel Silva #define OV2680_REG_TIMING_VTS 0x380e 43*3ee47cadSRui Miguel Silva #define OV2680_REG_FORMAT1 0x3820 44*3ee47cadSRui Miguel Silva #define OV2680_REG_FORMAT2 0x3821 45*3ee47cadSRui Miguel Silva 46*3ee47cadSRui Miguel Silva #define OV2680_REG_ISP_CTRL00 0x5080 47*3ee47cadSRui Miguel Silva 48*3ee47cadSRui Miguel Silva #define OV2680_FRAME_RATE 30 49*3ee47cadSRui Miguel Silva 50*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_8BIT 1 51*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_16BIT 2 52*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_24BIT 3 53*3ee47cadSRui Miguel Silva 54*3ee47cadSRui Miguel Silva #define OV2680_WIDTH_MAX 1600 55*3ee47cadSRui Miguel Silva #define OV2680_HEIGHT_MAX 1200 56*3ee47cadSRui Miguel Silva 57*3ee47cadSRui Miguel Silva enum ov2680_mode_id { 58*3ee47cadSRui Miguel Silva OV2680_MODE_QUXGA_800_600, 59*3ee47cadSRui Miguel Silva OV2680_MODE_720P_1280_720, 60*3ee47cadSRui Miguel Silva OV2680_MODE_UXGA_1600_1200, 61*3ee47cadSRui Miguel Silva OV2680_MODE_MAX, 62*3ee47cadSRui Miguel Silva }; 63*3ee47cadSRui Miguel Silva 64*3ee47cadSRui Miguel Silva struct reg_value { 65*3ee47cadSRui Miguel Silva u16 reg_addr; 66*3ee47cadSRui Miguel Silva u8 val; 67*3ee47cadSRui Miguel Silva }; 68*3ee47cadSRui Miguel Silva 69*3ee47cadSRui Miguel Silva static const char * const ov2680_supply_name[] = { 70*3ee47cadSRui Miguel Silva "DOVDD", 71*3ee47cadSRui Miguel Silva "DVDD", 72*3ee47cadSRui Miguel Silva "AVDD", 73*3ee47cadSRui Miguel Silva }; 74*3ee47cadSRui Miguel Silva 75*3ee47cadSRui Miguel Silva #define OV2680_NUM_SUPPLIES ARRAY_SIZE(ov2680_supply_name) 76*3ee47cadSRui Miguel Silva 77*3ee47cadSRui Miguel Silva struct ov2680_mode_info { 78*3ee47cadSRui Miguel Silva const char *name; 79*3ee47cadSRui Miguel Silva enum ov2680_mode_id id; 80*3ee47cadSRui Miguel Silva u32 width; 81*3ee47cadSRui Miguel Silva u32 height; 82*3ee47cadSRui Miguel Silva const struct reg_value *reg_data; 83*3ee47cadSRui Miguel Silva u32 reg_data_size; 84*3ee47cadSRui Miguel Silva }; 85*3ee47cadSRui Miguel Silva 86*3ee47cadSRui Miguel Silva struct ov2680_ctrls { 87*3ee47cadSRui Miguel Silva struct v4l2_ctrl_handler handler; 88*3ee47cadSRui Miguel Silva struct { 89*3ee47cadSRui Miguel Silva struct v4l2_ctrl *auto_exp; 90*3ee47cadSRui Miguel Silva struct v4l2_ctrl *exposure; 91*3ee47cadSRui Miguel Silva }; 92*3ee47cadSRui Miguel Silva struct { 93*3ee47cadSRui Miguel Silva struct v4l2_ctrl *auto_gain; 94*3ee47cadSRui Miguel Silva struct v4l2_ctrl *gain; 95*3ee47cadSRui Miguel Silva }; 96*3ee47cadSRui Miguel Silva 97*3ee47cadSRui Miguel Silva struct v4l2_ctrl *hflip; 98*3ee47cadSRui Miguel Silva struct v4l2_ctrl *vflip; 99*3ee47cadSRui Miguel Silva struct v4l2_ctrl *test_pattern; 100*3ee47cadSRui Miguel Silva }; 101*3ee47cadSRui Miguel Silva 102*3ee47cadSRui Miguel Silva struct ov2680_dev { 103*3ee47cadSRui Miguel Silva struct i2c_client *i2c_client; 104*3ee47cadSRui Miguel Silva struct v4l2_subdev sd; 105*3ee47cadSRui Miguel Silva 106*3ee47cadSRui Miguel Silva struct media_pad pad; 107*3ee47cadSRui Miguel Silva struct clk *xvclk; 108*3ee47cadSRui Miguel Silva u32 xvclk_freq; 109*3ee47cadSRui Miguel Silva struct regulator_bulk_data supplies[OV2680_NUM_SUPPLIES]; 110*3ee47cadSRui Miguel Silva 111*3ee47cadSRui Miguel Silva struct gpio_desc *reset_gpio; 112*3ee47cadSRui Miguel Silva struct mutex lock; /* protect members */ 113*3ee47cadSRui Miguel Silva 114*3ee47cadSRui Miguel Silva bool mode_pending_changes; 115*3ee47cadSRui Miguel Silva bool is_enabled; 116*3ee47cadSRui Miguel Silva bool is_streaming; 117*3ee47cadSRui Miguel Silva 118*3ee47cadSRui Miguel Silva struct ov2680_ctrls ctrls; 119*3ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt fmt; 120*3ee47cadSRui Miguel Silva struct v4l2_fract frame_interval; 121*3ee47cadSRui Miguel Silva 122*3ee47cadSRui Miguel Silva const struct ov2680_mode_info *current_mode; 123*3ee47cadSRui Miguel Silva }; 124*3ee47cadSRui Miguel Silva 125*3ee47cadSRui Miguel Silva static const char * const test_pattern_menu[] = { 126*3ee47cadSRui Miguel Silva "Disabled", 127*3ee47cadSRui Miguel Silva "Color Bars", 128*3ee47cadSRui Miguel Silva "Random Data", 129*3ee47cadSRui Miguel Silva "Square", 130*3ee47cadSRui Miguel Silva "Black Image", 131*3ee47cadSRui Miguel Silva }; 132*3ee47cadSRui Miguel Silva 133*3ee47cadSRui Miguel Silva static const int ov2680_hv_flip_bayer_order[] = { 134*3ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SBGGR10_1X10, 135*3ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SGRBG10_1X10, 136*3ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SGBRG10_1X10, 137*3ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SRGGB10_1X10, 138*3ee47cadSRui Miguel Silva }; 139*3ee47cadSRui Miguel Silva 140*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_QUXGA_800_600[] = { 141*3ee47cadSRui Miguel Silva {0x3086, 0x01}, {0x370a, 0x23}, {0x3808, 0x03}, {0x3809, 0x20}, 142*3ee47cadSRui Miguel Silva {0x380a, 0x02}, {0x380b, 0x58}, {0x380c, 0x06}, {0x380d, 0xac}, 143*3ee47cadSRui Miguel Silva {0x380e, 0x02}, {0x380f, 0x84}, {0x3811, 0x04}, {0x3813, 0x04}, 144*3ee47cadSRui Miguel Silva {0x3814, 0x31}, {0x3815, 0x31}, {0x3820, 0xc0}, {0x4008, 0x00}, 145*3ee47cadSRui Miguel Silva {0x4009, 0x03}, {0x4837, 0x1e}, {0x3501, 0x4e}, {0x3502, 0xe0}, 146*3ee47cadSRui Miguel Silva }; 147*3ee47cadSRui Miguel Silva 148*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_720P_1280_720[] = { 149*3ee47cadSRui Miguel Silva {0x3086, 0x00}, {0x3808, 0x05}, {0x3809, 0x00}, {0x380a, 0x02}, 150*3ee47cadSRui Miguel Silva {0x380b, 0xd0}, {0x380c, 0x06}, {0x380d, 0xa8}, {0x380e, 0x05}, 151*3ee47cadSRui Miguel Silva {0x380f, 0x0e}, {0x3811, 0x08}, {0x3813, 0x06}, {0x3814, 0x11}, 152*3ee47cadSRui Miguel Silva {0x3815, 0x11}, {0x3820, 0xc0}, {0x4008, 0x00}, 153*3ee47cadSRui Miguel Silva }; 154*3ee47cadSRui Miguel Silva 155*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_UXGA_1600_1200[] = { 156*3ee47cadSRui Miguel Silva {0x3086, 0x00}, {0x3501, 0x4e}, {0x3502, 0xe0}, {0x3808, 0x06}, 157*3ee47cadSRui Miguel Silva {0x3809, 0x40}, {0x380a, 0x04}, {0x380b, 0xb0}, {0x380c, 0x06}, 158*3ee47cadSRui Miguel Silva {0x380d, 0xa8}, {0x380e, 0x05}, {0x380f, 0x0e}, {0x3811, 0x00}, 159*3ee47cadSRui Miguel Silva {0x3813, 0x00}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3820, 0xc0}, 160*3ee47cadSRui Miguel Silva {0x4008, 0x00}, {0x4837, 0x18} 161*3ee47cadSRui Miguel Silva }; 162*3ee47cadSRui Miguel Silva 163*3ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_init_data = { 164*3ee47cadSRui Miguel Silva "mode_quxga_800_600", OV2680_MODE_QUXGA_800_600, 800, 600, 165*3ee47cadSRui Miguel Silva ov2680_setting_30fps_QUXGA_800_600, 166*3ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600), 167*3ee47cadSRui Miguel Silva }; 168*3ee47cadSRui Miguel Silva 169*3ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_data[OV2680_MODE_MAX] = { 170*3ee47cadSRui Miguel Silva {"mode_quxga_800_600", OV2680_MODE_QUXGA_800_600, 171*3ee47cadSRui Miguel Silva 800, 600, ov2680_setting_30fps_QUXGA_800_600, 172*3ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600)}, 173*3ee47cadSRui Miguel Silva {"mode_720p_1280_720", OV2680_MODE_720P_1280_720, 174*3ee47cadSRui Miguel Silva 1280, 720, ov2680_setting_30fps_720P_1280_720, 175*3ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_720P_1280_720)}, 176*3ee47cadSRui Miguel Silva {"mode_uxga_1600_1200", OV2680_MODE_UXGA_1600_1200, 177*3ee47cadSRui Miguel Silva 1600, 1200, ov2680_setting_30fps_UXGA_1600_1200, 178*3ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_UXGA_1600_1200)}, 179*3ee47cadSRui Miguel Silva }; 180*3ee47cadSRui Miguel Silva 181*3ee47cadSRui Miguel Silva static struct ov2680_dev *to_ov2680_dev(struct v4l2_subdev *sd) 182*3ee47cadSRui Miguel Silva { 183*3ee47cadSRui Miguel Silva return container_of(sd, struct ov2680_dev, sd); 184*3ee47cadSRui Miguel Silva } 185*3ee47cadSRui Miguel Silva 186*3ee47cadSRui Miguel Silva static struct device *ov2680_to_dev(struct ov2680_dev *sensor) 187*3ee47cadSRui Miguel Silva { 188*3ee47cadSRui Miguel Silva return &sensor->i2c_client->dev; 189*3ee47cadSRui Miguel Silva } 190*3ee47cadSRui Miguel Silva 191*3ee47cadSRui Miguel Silva static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) 192*3ee47cadSRui Miguel Silva { 193*3ee47cadSRui Miguel Silva return &container_of(ctrl->handler, struct ov2680_dev, 194*3ee47cadSRui Miguel Silva ctrls.handler)->sd; 195*3ee47cadSRui Miguel Silva } 196*3ee47cadSRui Miguel Silva 197*3ee47cadSRui Miguel Silva static int __ov2680_write_reg(struct ov2680_dev *sensor, u16 reg, 198*3ee47cadSRui Miguel Silva unsigned int len, u32 val) 199*3ee47cadSRui Miguel Silva { 200*3ee47cadSRui Miguel Silva struct i2c_client *client = sensor->i2c_client; 201*3ee47cadSRui Miguel Silva u8 buf[6]; 202*3ee47cadSRui Miguel Silva int ret; 203*3ee47cadSRui Miguel Silva 204*3ee47cadSRui Miguel Silva if (len > 4) 205*3ee47cadSRui Miguel Silva return -EINVAL; 206*3ee47cadSRui Miguel Silva 207*3ee47cadSRui Miguel Silva put_unaligned_be16(reg, buf); 208*3ee47cadSRui Miguel Silva put_unaligned_be32(val << (8 * (4 - len)), buf + 2); 209*3ee47cadSRui Miguel Silva ret = i2c_master_send(client, buf, len + 2); 210*3ee47cadSRui Miguel Silva if (ret != len + 2) { 211*3ee47cadSRui Miguel Silva dev_err(&client->dev, "write error: reg=0x%4x: %d\n", reg, ret); 212*3ee47cadSRui Miguel Silva return -EIO; 213*3ee47cadSRui Miguel Silva } 214*3ee47cadSRui Miguel Silva 215*3ee47cadSRui Miguel Silva return 0; 216*3ee47cadSRui Miguel Silva } 217*3ee47cadSRui Miguel Silva 218*3ee47cadSRui Miguel Silva #define ov2680_write_reg(s, r, v) \ 219*3ee47cadSRui Miguel Silva __ov2680_write_reg(s, r, OV2680_REG_VALUE_8BIT, v) 220*3ee47cadSRui Miguel Silva 221*3ee47cadSRui Miguel Silva #define ov2680_write_reg16(s, r, v) \ 222*3ee47cadSRui Miguel Silva __ov2680_write_reg(s, r, OV2680_REG_VALUE_16BIT, v) 223*3ee47cadSRui Miguel Silva 224*3ee47cadSRui Miguel Silva #define ov2680_write_reg24(s, r, v) \ 225*3ee47cadSRui Miguel Silva __ov2680_write_reg(s, r, OV2680_REG_VALUE_24BIT, v) 226*3ee47cadSRui Miguel Silva 227*3ee47cadSRui Miguel Silva static int __ov2680_read_reg(struct ov2680_dev *sensor, u16 reg, 228*3ee47cadSRui Miguel Silva unsigned int len, u32 *val) 229*3ee47cadSRui Miguel Silva { 230*3ee47cadSRui Miguel Silva struct i2c_client *client = sensor->i2c_client; 231*3ee47cadSRui Miguel Silva struct i2c_msg msgs[2]; 232*3ee47cadSRui Miguel Silva u8 addr_buf[2] = { reg >> 8, reg & 0xff }; 233*3ee47cadSRui Miguel Silva u8 data_buf[4] = { 0, }; 234*3ee47cadSRui Miguel Silva int ret; 235*3ee47cadSRui Miguel Silva 236*3ee47cadSRui Miguel Silva if (len > 4) 237*3ee47cadSRui Miguel Silva return -EINVAL; 238*3ee47cadSRui Miguel Silva 239*3ee47cadSRui Miguel Silva msgs[0].addr = client->addr; 240*3ee47cadSRui Miguel Silva msgs[0].flags = 0; 241*3ee47cadSRui Miguel Silva msgs[0].len = ARRAY_SIZE(addr_buf); 242*3ee47cadSRui Miguel Silva msgs[0].buf = addr_buf; 243*3ee47cadSRui Miguel Silva 244*3ee47cadSRui Miguel Silva msgs[1].addr = client->addr; 245*3ee47cadSRui Miguel Silva msgs[1].flags = I2C_M_RD; 246*3ee47cadSRui Miguel Silva msgs[1].len = len; 247*3ee47cadSRui Miguel Silva msgs[1].buf = &data_buf[4 - len]; 248*3ee47cadSRui Miguel Silva 249*3ee47cadSRui Miguel Silva ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 250*3ee47cadSRui Miguel Silva if (ret != ARRAY_SIZE(msgs)) { 251*3ee47cadSRui Miguel Silva dev_err(&client->dev, "read error: reg=0x%4x: %d\n", reg, ret); 252*3ee47cadSRui Miguel Silva return -EIO; 253*3ee47cadSRui Miguel Silva } 254*3ee47cadSRui Miguel Silva 255*3ee47cadSRui Miguel Silva *val = get_unaligned_be32(data_buf); 256*3ee47cadSRui Miguel Silva 257*3ee47cadSRui Miguel Silva return 0; 258*3ee47cadSRui Miguel Silva } 259*3ee47cadSRui Miguel Silva 260*3ee47cadSRui Miguel Silva #define ov2680_read_reg(s, r, v) \ 261*3ee47cadSRui Miguel Silva __ov2680_read_reg(s, r, OV2680_REG_VALUE_8BIT, v) 262*3ee47cadSRui Miguel Silva 263*3ee47cadSRui Miguel Silva #define ov2680_read_reg16(s, r, v) \ 264*3ee47cadSRui Miguel Silva __ov2680_read_reg(s, r, OV2680_REG_VALUE_16BIT, v) 265*3ee47cadSRui Miguel Silva 266*3ee47cadSRui Miguel Silva #define ov2680_read_reg24(s, r, v) \ 267*3ee47cadSRui Miguel Silva __ov2680_read_reg(s, r, OV2680_REG_VALUE_24BIT, v) 268*3ee47cadSRui Miguel Silva 269*3ee47cadSRui Miguel Silva static int ov2680_mod_reg(struct ov2680_dev *sensor, u16 reg, u8 mask, u8 val) 270*3ee47cadSRui Miguel Silva { 271*3ee47cadSRui Miguel Silva u32 readval; 272*3ee47cadSRui Miguel Silva int ret; 273*3ee47cadSRui Miguel Silva 274*3ee47cadSRui Miguel Silva ret = ov2680_read_reg(sensor, reg, &readval); 275*3ee47cadSRui Miguel Silva if (ret < 0) 276*3ee47cadSRui Miguel Silva return ret; 277*3ee47cadSRui Miguel Silva 278*3ee47cadSRui Miguel Silva readval &= ~mask; 279*3ee47cadSRui Miguel Silva val &= mask; 280*3ee47cadSRui Miguel Silva val |= readval; 281*3ee47cadSRui Miguel Silva 282*3ee47cadSRui Miguel Silva return ov2680_write_reg(sensor, reg, val); 283*3ee47cadSRui Miguel Silva } 284*3ee47cadSRui Miguel Silva 285*3ee47cadSRui Miguel Silva static int ov2680_load_regs(struct ov2680_dev *sensor, 286*3ee47cadSRui Miguel Silva const struct ov2680_mode_info *mode) 287*3ee47cadSRui Miguel Silva { 288*3ee47cadSRui Miguel Silva const struct reg_value *regs = mode->reg_data; 289*3ee47cadSRui Miguel Silva unsigned int i; 290*3ee47cadSRui Miguel Silva int ret = 0; 291*3ee47cadSRui Miguel Silva u16 reg_addr; 292*3ee47cadSRui Miguel Silva u8 val; 293*3ee47cadSRui Miguel Silva 294*3ee47cadSRui Miguel Silva for (i = 0; i < mode->reg_data_size; ++i, ++regs) { 295*3ee47cadSRui Miguel Silva reg_addr = regs->reg_addr; 296*3ee47cadSRui Miguel Silva val = regs->val; 297*3ee47cadSRui Miguel Silva 298*3ee47cadSRui Miguel Silva ret = ov2680_write_reg(sensor, reg_addr, val); 299*3ee47cadSRui Miguel Silva if (ret) 300*3ee47cadSRui Miguel Silva break; 301*3ee47cadSRui Miguel Silva } 302*3ee47cadSRui Miguel Silva 303*3ee47cadSRui Miguel Silva return ret; 304*3ee47cadSRui Miguel Silva } 305*3ee47cadSRui Miguel Silva 306*3ee47cadSRui Miguel Silva static void ov2680_power_up(struct ov2680_dev *sensor) 307*3ee47cadSRui Miguel Silva { 308*3ee47cadSRui Miguel Silva if (!sensor->reset_gpio) 309*3ee47cadSRui Miguel Silva return; 310*3ee47cadSRui Miguel Silva 311*3ee47cadSRui Miguel Silva gpiod_set_value(sensor->reset_gpio, 0); 312*3ee47cadSRui Miguel Silva usleep_range(5000, 10000); 313*3ee47cadSRui Miguel Silva } 314*3ee47cadSRui Miguel Silva 315*3ee47cadSRui Miguel Silva static void ov2680_power_down(struct ov2680_dev *sensor) 316*3ee47cadSRui Miguel Silva { 317*3ee47cadSRui Miguel Silva if (!sensor->reset_gpio) 318*3ee47cadSRui Miguel Silva return; 319*3ee47cadSRui Miguel Silva 320*3ee47cadSRui Miguel Silva gpiod_set_value(sensor->reset_gpio, 1); 321*3ee47cadSRui Miguel Silva usleep_range(5000, 10000); 322*3ee47cadSRui Miguel Silva } 323*3ee47cadSRui Miguel Silva 324*3ee47cadSRui Miguel Silva static int ov2680_bayer_order(struct ov2680_dev *sensor) 325*3ee47cadSRui Miguel Silva { 326*3ee47cadSRui Miguel Silva u32 format1; 327*3ee47cadSRui Miguel Silva u32 format2; 328*3ee47cadSRui Miguel Silva u32 hv_flip; 329*3ee47cadSRui Miguel Silva int ret; 330*3ee47cadSRui Miguel Silva 331*3ee47cadSRui Miguel Silva ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT1, &format1); 332*3ee47cadSRui Miguel Silva if (ret < 0) 333*3ee47cadSRui Miguel Silva return ret; 334*3ee47cadSRui Miguel Silva 335*3ee47cadSRui Miguel Silva ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT2, &format2); 336*3ee47cadSRui Miguel Silva if (ret < 0) 337*3ee47cadSRui Miguel Silva return ret; 338*3ee47cadSRui Miguel Silva 339*3ee47cadSRui Miguel Silva hv_flip = (format2 & BIT(2) << 1) | (format1 & BIT(2)); 340*3ee47cadSRui Miguel Silva 341*3ee47cadSRui Miguel Silva sensor->fmt.code = ov2680_hv_flip_bayer_order[hv_flip]; 342*3ee47cadSRui Miguel Silva 343*3ee47cadSRui Miguel Silva return 0; 344*3ee47cadSRui Miguel Silva } 345*3ee47cadSRui Miguel Silva 346*3ee47cadSRui Miguel Silva static int ov2680_vflip_enable(struct ov2680_dev *sensor) 347*3ee47cadSRui Miguel Silva { 348*3ee47cadSRui Miguel Silva int ret; 349*3ee47cadSRui Miguel Silva 350*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(2)); 351*3ee47cadSRui Miguel Silva if (ret < 0) 352*3ee47cadSRui Miguel Silva return ret; 353*3ee47cadSRui Miguel Silva 354*3ee47cadSRui Miguel Silva return ov2680_bayer_order(sensor); 355*3ee47cadSRui Miguel Silva } 356*3ee47cadSRui Miguel Silva 357*3ee47cadSRui Miguel Silva static int ov2680_vflip_disable(struct ov2680_dev *sensor) 358*3ee47cadSRui Miguel Silva { 359*3ee47cadSRui Miguel Silva int ret; 360*3ee47cadSRui Miguel Silva 361*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(0)); 362*3ee47cadSRui Miguel Silva if (ret < 0) 363*3ee47cadSRui Miguel Silva return ret; 364*3ee47cadSRui Miguel Silva 365*3ee47cadSRui Miguel Silva return ov2680_bayer_order(sensor); 366*3ee47cadSRui Miguel Silva } 367*3ee47cadSRui Miguel Silva 368*3ee47cadSRui Miguel Silva static int ov2680_hflip_enable(struct ov2680_dev *sensor) 369*3ee47cadSRui Miguel Silva { 370*3ee47cadSRui Miguel Silva int ret; 371*3ee47cadSRui Miguel Silva 372*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(2)); 373*3ee47cadSRui Miguel Silva if (ret < 0) 374*3ee47cadSRui Miguel Silva return ret; 375*3ee47cadSRui Miguel Silva 376*3ee47cadSRui Miguel Silva return ov2680_bayer_order(sensor); 377*3ee47cadSRui Miguel Silva } 378*3ee47cadSRui Miguel Silva 379*3ee47cadSRui Miguel Silva static int ov2680_hflip_disable(struct ov2680_dev *sensor) 380*3ee47cadSRui Miguel Silva { 381*3ee47cadSRui Miguel Silva int ret; 382*3ee47cadSRui Miguel Silva 383*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(0)); 384*3ee47cadSRui Miguel Silva if (ret < 0) 385*3ee47cadSRui Miguel Silva return ret; 386*3ee47cadSRui Miguel Silva 387*3ee47cadSRui Miguel Silva return ov2680_bayer_order(sensor); 388*3ee47cadSRui Miguel Silva } 389*3ee47cadSRui Miguel Silva 390*3ee47cadSRui Miguel Silva static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) 391*3ee47cadSRui Miguel Silva { 392*3ee47cadSRui Miguel Silva int ret; 393*3ee47cadSRui Miguel Silva 394*3ee47cadSRui Miguel Silva if (!value) 395*3ee47cadSRui Miguel Silva return ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, BIT(7), 0); 396*3ee47cadSRui Miguel Silva 397*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, 0x03, value - 1); 398*3ee47cadSRui Miguel Silva if (ret < 0) 399*3ee47cadSRui Miguel Silva return ret; 400*3ee47cadSRui Miguel Silva 401*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, BIT(7), BIT(7)); 402*3ee47cadSRui Miguel Silva if (ret < 0) 403*3ee47cadSRui Miguel Silva return ret; 404*3ee47cadSRui Miguel Silva 405*3ee47cadSRui Miguel Silva return 0; 406*3ee47cadSRui Miguel Silva } 407*3ee47cadSRui Miguel Silva 408*3ee47cadSRui Miguel Silva static int ov2680_gain_set(struct ov2680_dev *sensor, bool auto_gain) 409*3ee47cadSRui Miguel Silva { 410*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 411*3ee47cadSRui Miguel Silva u32 gain; 412*3ee47cadSRui Miguel Silva int ret; 413*3ee47cadSRui Miguel Silva 414*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(1), 415*3ee47cadSRui Miguel Silva auto_gain ? 0 : BIT(1)); 416*3ee47cadSRui Miguel Silva if (ret < 0) 417*3ee47cadSRui Miguel Silva return ret; 418*3ee47cadSRui Miguel Silva 419*3ee47cadSRui Miguel Silva if (auto_gain || !ctrls->gain->is_new) 420*3ee47cadSRui Miguel Silva return 0; 421*3ee47cadSRui Miguel Silva 422*3ee47cadSRui Miguel Silva gain = ctrls->gain->val; 423*3ee47cadSRui Miguel Silva 424*3ee47cadSRui Miguel Silva ret = ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain); 425*3ee47cadSRui Miguel Silva 426*3ee47cadSRui Miguel Silva return 0; 427*3ee47cadSRui Miguel Silva } 428*3ee47cadSRui Miguel Silva 429*3ee47cadSRui Miguel Silva static int ov2680_gain_get(struct ov2680_dev *sensor) 430*3ee47cadSRui Miguel Silva { 431*3ee47cadSRui Miguel Silva u32 gain; 432*3ee47cadSRui Miguel Silva int ret; 433*3ee47cadSRui Miguel Silva 434*3ee47cadSRui Miguel Silva ret = ov2680_read_reg16(sensor, OV2680_REG_GAIN_PK, &gain); 435*3ee47cadSRui Miguel Silva if (ret) 436*3ee47cadSRui Miguel Silva return ret; 437*3ee47cadSRui Miguel Silva 438*3ee47cadSRui Miguel Silva return gain; 439*3ee47cadSRui Miguel Silva } 440*3ee47cadSRui Miguel Silva 441*3ee47cadSRui Miguel Silva static int ov2680_exposure_set(struct ov2680_dev *sensor, bool auto_exp) 442*3ee47cadSRui Miguel Silva { 443*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 444*3ee47cadSRui Miguel Silva u32 exp; 445*3ee47cadSRui Miguel Silva int ret; 446*3ee47cadSRui Miguel Silva 447*3ee47cadSRui Miguel Silva ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(0), 448*3ee47cadSRui Miguel Silva auto_exp ? 0 : BIT(0)); 449*3ee47cadSRui Miguel Silva if (ret < 0) 450*3ee47cadSRui Miguel Silva return ret; 451*3ee47cadSRui Miguel Silva 452*3ee47cadSRui Miguel Silva if (auto_exp || !ctrls->exposure->is_new) 453*3ee47cadSRui Miguel Silva return 0; 454*3ee47cadSRui Miguel Silva 455*3ee47cadSRui Miguel Silva exp = (u32)ctrls->exposure->val; 456*3ee47cadSRui Miguel Silva exp <<= 4; 457*3ee47cadSRui Miguel Silva 458*3ee47cadSRui Miguel Silva return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, exp); 459*3ee47cadSRui Miguel Silva } 460*3ee47cadSRui Miguel Silva 461*3ee47cadSRui Miguel Silva static int ov2680_exposure_get(struct ov2680_dev *sensor) 462*3ee47cadSRui Miguel Silva { 463*3ee47cadSRui Miguel Silva int ret; 464*3ee47cadSRui Miguel Silva u32 exp; 465*3ee47cadSRui Miguel Silva 466*3ee47cadSRui Miguel Silva ret = ov2680_read_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, &exp); 467*3ee47cadSRui Miguel Silva if (ret) 468*3ee47cadSRui Miguel Silva return ret; 469*3ee47cadSRui Miguel Silva 470*3ee47cadSRui Miguel Silva return exp >> 4; 471*3ee47cadSRui Miguel Silva } 472*3ee47cadSRui Miguel Silva 473*3ee47cadSRui Miguel Silva static int ov2680_stream_enable(struct ov2680_dev *sensor) 474*3ee47cadSRui Miguel Silva { 475*3ee47cadSRui Miguel Silva return ov2680_write_reg(sensor, OV2680_REG_STREAM_CTRL, 1); 476*3ee47cadSRui Miguel Silva } 477*3ee47cadSRui Miguel Silva 478*3ee47cadSRui Miguel Silva static int ov2680_stream_disable(struct ov2680_dev *sensor) 479*3ee47cadSRui Miguel Silva { 480*3ee47cadSRui Miguel Silva return ov2680_write_reg(sensor, OV2680_REG_STREAM_CTRL, 0); 481*3ee47cadSRui Miguel Silva } 482*3ee47cadSRui Miguel Silva 483*3ee47cadSRui Miguel Silva static int ov2680_mode_set(struct ov2680_dev *sensor) 484*3ee47cadSRui Miguel Silva { 485*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 486*3ee47cadSRui Miguel Silva int ret; 487*3ee47cadSRui Miguel Silva 488*3ee47cadSRui Miguel Silva ret = ov2680_gain_set(sensor, false); 489*3ee47cadSRui Miguel Silva if (ret < 0) 490*3ee47cadSRui Miguel Silva return ret; 491*3ee47cadSRui Miguel Silva 492*3ee47cadSRui Miguel Silva ret = ov2680_exposure_set(sensor, false); 493*3ee47cadSRui Miguel Silva if (ret < 0) 494*3ee47cadSRui Miguel Silva return ret; 495*3ee47cadSRui Miguel Silva 496*3ee47cadSRui Miguel Silva ret = ov2680_load_regs(sensor, sensor->current_mode); 497*3ee47cadSRui Miguel Silva if (ret < 0) 498*3ee47cadSRui Miguel Silva return ret; 499*3ee47cadSRui Miguel Silva 500*3ee47cadSRui Miguel Silva if (ctrls->auto_gain->val) { 501*3ee47cadSRui Miguel Silva ret = ov2680_gain_set(sensor, true); 502*3ee47cadSRui Miguel Silva if (ret < 0) 503*3ee47cadSRui Miguel Silva return ret; 504*3ee47cadSRui Miguel Silva } 505*3ee47cadSRui Miguel Silva 506*3ee47cadSRui Miguel Silva if (ctrls->auto_exp->val == V4L2_EXPOSURE_AUTO) { 507*3ee47cadSRui Miguel Silva ret = ov2680_exposure_set(sensor, true); 508*3ee47cadSRui Miguel Silva if (ret < 0) 509*3ee47cadSRui Miguel Silva return ret; 510*3ee47cadSRui Miguel Silva } 511*3ee47cadSRui Miguel Silva 512*3ee47cadSRui Miguel Silva sensor->mode_pending_changes = false; 513*3ee47cadSRui Miguel Silva 514*3ee47cadSRui Miguel Silva return 0; 515*3ee47cadSRui Miguel Silva } 516*3ee47cadSRui Miguel Silva 517*3ee47cadSRui Miguel Silva static int ov2680_mode_restore(struct ov2680_dev *sensor) 518*3ee47cadSRui Miguel Silva { 519*3ee47cadSRui Miguel Silva int ret; 520*3ee47cadSRui Miguel Silva 521*3ee47cadSRui Miguel Silva ret = ov2680_load_regs(sensor, &ov2680_mode_init_data); 522*3ee47cadSRui Miguel Silva if (ret < 0) 523*3ee47cadSRui Miguel Silva return ret; 524*3ee47cadSRui Miguel Silva 525*3ee47cadSRui Miguel Silva return ov2680_mode_set(sensor); 526*3ee47cadSRui Miguel Silva } 527*3ee47cadSRui Miguel Silva 528*3ee47cadSRui Miguel Silva static int ov2680_power_off(struct ov2680_dev *sensor) 529*3ee47cadSRui Miguel Silva { 530*3ee47cadSRui Miguel Silva if (!sensor->is_enabled) 531*3ee47cadSRui Miguel Silva return 0; 532*3ee47cadSRui Miguel Silva 533*3ee47cadSRui Miguel Silva clk_disable_unprepare(sensor->xvclk); 534*3ee47cadSRui Miguel Silva ov2680_power_down(sensor); 535*3ee47cadSRui Miguel Silva regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies); 536*3ee47cadSRui Miguel Silva sensor->is_enabled = false; 537*3ee47cadSRui Miguel Silva 538*3ee47cadSRui Miguel Silva return 0; 539*3ee47cadSRui Miguel Silva } 540*3ee47cadSRui Miguel Silva 541*3ee47cadSRui Miguel Silva static int ov2680_power_on(struct ov2680_dev *sensor) 542*3ee47cadSRui Miguel Silva { 543*3ee47cadSRui Miguel Silva struct device *dev = ov2680_to_dev(sensor); 544*3ee47cadSRui Miguel Silva int ret; 545*3ee47cadSRui Miguel Silva 546*3ee47cadSRui Miguel Silva if (sensor->is_enabled) 547*3ee47cadSRui Miguel Silva return 0; 548*3ee47cadSRui Miguel Silva 549*3ee47cadSRui Miguel Silva ret = regulator_bulk_enable(OV2680_NUM_SUPPLIES, sensor->supplies); 550*3ee47cadSRui Miguel Silva if (ret < 0) { 551*3ee47cadSRui Miguel Silva dev_err(dev, "failed to enable regulators: %d\n", ret); 552*3ee47cadSRui Miguel Silva return ret; 553*3ee47cadSRui Miguel Silva } 554*3ee47cadSRui Miguel Silva 555*3ee47cadSRui Miguel Silva if (!sensor->reset_gpio) { 556*3ee47cadSRui Miguel Silva ret = ov2680_write_reg(sensor, OV2680_REG_SOFT_RESET, 0x01); 557*3ee47cadSRui Miguel Silva if (ret != 0) { 558*3ee47cadSRui Miguel Silva dev_err(dev, "sensor soft reset failed\n"); 559*3ee47cadSRui Miguel Silva return ret; 560*3ee47cadSRui Miguel Silva } 561*3ee47cadSRui Miguel Silva usleep_range(1000, 2000); 562*3ee47cadSRui Miguel Silva } else { 563*3ee47cadSRui Miguel Silva ov2680_power_down(sensor); 564*3ee47cadSRui Miguel Silva ov2680_power_up(sensor); 565*3ee47cadSRui Miguel Silva } 566*3ee47cadSRui Miguel Silva 567*3ee47cadSRui Miguel Silva ret = clk_prepare_enable(sensor->xvclk); 568*3ee47cadSRui Miguel Silva if (ret < 0) 569*3ee47cadSRui Miguel Silva return ret; 570*3ee47cadSRui Miguel Silva 571*3ee47cadSRui Miguel Silva ret = ov2680_mode_restore(sensor); 572*3ee47cadSRui Miguel Silva if (ret < 0) 573*3ee47cadSRui Miguel Silva goto disable; 574*3ee47cadSRui Miguel Silva 575*3ee47cadSRui Miguel Silva sensor->is_enabled = true; 576*3ee47cadSRui Miguel Silva 577*3ee47cadSRui Miguel Silva /* Set clock lane into LP-11 state */ 578*3ee47cadSRui Miguel Silva ov2680_stream_enable(sensor); 579*3ee47cadSRui Miguel Silva usleep_range(1000, 2000); 580*3ee47cadSRui Miguel Silva ov2680_stream_disable(sensor); 581*3ee47cadSRui Miguel Silva 582*3ee47cadSRui Miguel Silva return 0; 583*3ee47cadSRui Miguel Silva 584*3ee47cadSRui Miguel Silva disable: 585*3ee47cadSRui Miguel Silva dev_err(dev, "failed to enable sensor: %d\n", ret); 586*3ee47cadSRui Miguel Silva ov2680_power_off(sensor); 587*3ee47cadSRui Miguel Silva 588*3ee47cadSRui Miguel Silva return ret; 589*3ee47cadSRui Miguel Silva } 590*3ee47cadSRui Miguel Silva 591*3ee47cadSRui Miguel Silva static int ov2680_s_power(struct v4l2_subdev *sd, int on) 592*3ee47cadSRui Miguel Silva { 593*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 594*3ee47cadSRui Miguel Silva int ret = 0; 595*3ee47cadSRui Miguel Silva 596*3ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 597*3ee47cadSRui Miguel Silva 598*3ee47cadSRui Miguel Silva if (on) 599*3ee47cadSRui Miguel Silva ret = ov2680_power_on(sensor); 600*3ee47cadSRui Miguel Silva else 601*3ee47cadSRui Miguel Silva ret = ov2680_power_off(sensor); 602*3ee47cadSRui Miguel Silva 603*3ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 604*3ee47cadSRui Miguel Silva 605*3ee47cadSRui Miguel Silva if (on && ret == 0) { 606*3ee47cadSRui Miguel Silva ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler); 607*3ee47cadSRui Miguel Silva if (ret < 0) 608*3ee47cadSRui Miguel Silva return ret; 609*3ee47cadSRui Miguel Silva } 610*3ee47cadSRui Miguel Silva 611*3ee47cadSRui Miguel Silva return ret; 612*3ee47cadSRui Miguel Silva } 613*3ee47cadSRui Miguel Silva 614*3ee47cadSRui Miguel Silva static int ov2680_s_g_frame_interval(struct v4l2_subdev *sd, 615*3ee47cadSRui Miguel Silva struct v4l2_subdev_frame_interval *fi) 616*3ee47cadSRui Miguel Silva { 617*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 618*3ee47cadSRui Miguel Silva 619*3ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 620*3ee47cadSRui Miguel Silva fi->interval = sensor->frame_interval; 621*3ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 622*3ee47cadSRui Miguel Silva 623*3ee47cadSRui Miguel Silva return 0; 624*3ee47cadSRui Miguel Silva } 625*3ee47cadSRui Miguel Silva 626*3ee47cadSRui Miguel Silva static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) 627*3ee47cadSRui Miguel Silva { 628*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 629*3ee47cadSRui Miguel Silva int ret = 0; 630*3ee47cadSRui Miguel Silva 631*3ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 632*3ee47cadSRui Miguel Silva 633*3ee47cadSRui Miguel Silva if (sensor->is_streaming == !!enable) 634*3ee47cadSRui Miguel Silva goto unlock; 635*3ee47cadSRui Miguel Silva 636*3ee47cadSRui Miguel Silva if (enable && sensor->mode_pending_changes) { 637*3ee47cadSRui Miguel Silva ret = ov2680_mode_set(sensor); 638*3ee47cadSRui Miguel Silva if (ret < 0) 639*3ee47cadSRui Miguel Silva goto unlock; 640*3ee47cadSRui Miguel Silva } 641*3ee47cadSRui Miguel Silva 642*3ee47cadSRui Miguel Silva if (enable) 643*3ee47cadSRui Miguel Silva ret = ov2680_stream_enable(sensor); 644*3ee47cadSRui Miguel Silva else 645*3ee47cadSRui Miguel Silva ret = ov2680_stream_disable(sensor); 646*3ee47cadSRui Miguel Silva 647*3ee47cadSRui Miguel Silva sensor->is_streaming = !!enable; 648*3ee47cadSRui Miguel Silva 649*3ee47cadSRui Miguel Silva unlock: 650*3ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 651*3ee47cadSRui Miguel Silva 652*3ee47cadSRui Miguel Silva return ret; 653*3ee47cadSRui Miguel Silva } 654*3ee47cadSRui Miguel Silva 655*3ee47cadSRui Miguel Silva static int ov2680_enum_mbus_code(struct v4l2_subdev *sd, 656*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg, 657*3ee47cadSRui Miguel Silva struct v4l2_subdev_mbus_code_enum *code) 658*3ee47cadSRui Miguel Silva { 659*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 660*3ee47cadSRui Miguel Silva 661*3ee47cadSRui Miguel Silva if (code->pad != 0 || code->index != 0) 662*3ee47cadSRui Miguel Silva return -EINVAL; 663*3ee47cadSRui Miguel Silva 664*3ee47cadSRui Miguel Silva code->code = sensor->fmt.code; 665*3ee47cadSRui Miguel Silva 666*3ee47cadSRui Miguel Silva return 0; 667*3ee47cadSRui Miguel Silva } 668*3ee47cadSRui Miguel Silva 669*3ee47cadSRui Miguel Silva static int ov2680_get_fmt(struct v4l2_subdev *sd, 670*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg, 671*3ee47cadSRui Miguel Silva struct v4l2_subdev_format *format) 672*3ee47cadSRui Miguel Silva { 673*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 674*3ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt *fmt = NULL; 675*3ee47cadSRui Miguel Silva int ret = 0; 676*3ee47cadSRui Miguel Silva 677*3ee47cadSRui Miguel Silva if (format->pad != 0) 678*3ee47cadSRui Miguel Silva return -EINVAL; 679*3ee47cadSRui Miguel Silva 680*3ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 681*3ee47cadSRui Miguel Silva 682*3ee47cadSRui Miguel Silva if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 683*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 684*3ee47cadSRui Miguel Silva fmt = v4l2_subdev_get_try_format(&sensor->sd, cfg, format->pad); 685*3ee47cadSRui Miguel Silva #else 686*3ee47cadSRui Miguel Silva ret = -ENOTTY; 687*3ee47cadSRui Miguel Silva #endif 688*3ee47cadSRui Miguel Silva } else { 689*3ee47cadSRui Miguel Silva fmt = &sensor->fmt; 690*3ee47cadSRui Miguel Silva } 691*3ee47cadSRui Miguel Silva 692*3ee47cadSRui Miguel Silva if (fmt) 693*3ee47cadSRui Miguel Silva format->format = *fmt; 694*3ee47cadSRui Miguel Silva 695*3ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 696*3ee47cadSRui Miguel Silva 697*3ee47cadSRui Miguel Silva return ret; 698*3ee47cadSRui Miguel Silva } 699*3ee47cadSRui Miguel Silva 700*3ee47cadSRui Miguel Silva static int ov2680_set_fmt(struct v4l2_subdev *sd, 701*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg, 702*3ee47cadSRui Miguel Silva struct v4l2_subdev_format *format) 703*3ee47cadSRui Miguel Silva { 704*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 705*3ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt *fmt = &format->format; 706*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 707*3ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt *try_fmt; 708*3ee47cadSRui Miguel Silva #endif 709*3ee47cadSRui Miguel Silva const struct ov2680_mode_info *mode; 710*3ee47cadSRui Miguel Silva int ret = 0; 711*3ee47cadSRui Miguel Silva 712*3ee47cadSRui Miguel Silva if (format->pad != 0) 713*3ee47cadSRui Miguel Silva return -EINVAL; 714*3ee47cadSRui Miguel Silva 715*3ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 716*3ee47cadSRui Miguel Silva 717*3ee47cadSRui Miguel Silva if (sensor->is_streaming) { 718*3ee47cadSRui Miguel Silva ret = -EBUSY; 719*3ee47cadSRui Miguel Silva goto unlock; 720*3ee47cadSRui Miguel Silva } 721*3ee47cadSRui Miguel Silva 722*3ee47cadSRui Miguel Silva mode = v4l2_find_nearest_size(ov2680_mode_data, 723*3ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_mode_data), width, 724*3ee47cadSRui Miguel Silva height, fmt->width, fmt->height); 725*3ee47cadSRui Miguel Silva if (!mode) { 726*3ee47cadSRui Miguel Silva ret = -EINVAL; 727*3ee47cadSRui Miguel Silva goto unlock; 728*3ee47cadSRui Miguel Silva } 729*3ee47cadSRui Miguel Silva 730*3ee47cadSRui Miguel Silva if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 731*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 732*3ee47cadSRui Miguel Silva try_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); 733*3ee47cadSRui Miguel Silva format->format = *try_fmt; 734*3ee47cadSRui Miguel Silva #else 735*3ee47cadSRui Miguel Silva ret = -ENOTTY; 736*3ee47cadSRui Miguel Silva #endif 737*3ee47cadSRui Miguel Silva 738*3ee47cadSRui Miguel Silva goto unlock; 739*3ee47cadSRui Miguel Silva } 740*3ee47cadSRui Miguel Silva 741*3ee47cadSRui Miguel Silva fmt->width = mode->width; 742*3ee47cadSRui Miguel Silva fmt->height = mode->height; 743*3ee47cadSRui Miguel Silva fmt->code = sensor->fmt.code; 744*3ee47cadSRui Miguel Silva fmt->colorspace = sensor->fmt.colorspace; 745*3ee47cadSRui Miguel Silva 746*3ee47cadSRui Miguel Silva sensor->current_mode = mode; 747*3ee47cadSRui Miguel Silva sensor->fmt = format->format; 748*3ee47cadSRui Miguel Silva sensor->mode_pending_changes = true; 749*3ee47cadSRui Miguel Silva 750*3ee47cadSRui Miguel Silva unlock: 751*3ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 752*3ee47cadSRui Miguel Silva 753*3ee47cadSRui Miguel Silva return ret; 754*3ee47cadSRui Miguel Silva } 755*3ee47cadSRui Miguel Silva 756*3ee47cadSRui Miguel Silva static int ov2680_init_cfg(struct v4l2_subdev *sd, 757*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg) 758*3ee47cadSRui Miguel Silva { 759*3ee47cadSRui Miguel Silva struct v4l2_subdev_format fmt = { 760*3ee47cadSRui Miguel Silva .which = cfg ? V4L2_SUBDEV_FORMAT_TRY 761*3ee47cadSRui Miguel Silva : V4L2_SUBDEV_FORMAT_ACTIVE, 762*3ee47cadSRui Miguel Silva .format = { 763*3ee47cadSRui Miguel Silva .width = 800, 764*3ee47cadSRui Miguel Silva .height = 600, 765*3ee47cadSRui Miguel Silva } 766*3ee47cadSRui Miguel Silva }; 767*3ee47cadSRui Miguel Silva 768*3ee47cadSRui Miguel Silva return ov2680_set_fmt(sd, cfg, &fmt); 769*3ee47cadSRui Miguel Silva } 770*3ee47cadSRui Miguel Silva 771*3ee47cadSRui Miguel Silva static int ov2680_enum_frame_size(struct v4l2_subdev *sd, 772*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg, 773*3ee47cadSRui Miguel Silva struct v4l2_subdev_frame_size_enum *fse) 774*3ee47cadSRui Miguel Silva { 775*3ee47cadSRui Miguel Silva int index = fse->index; 776*3ee47cadSRui Miguel Silva 777*3ee47cadSRui Miguel Silva if (index >= OV2680_MODE_MAX || index < 0) 778*3ee47cadSRui Miguel Silva return -EINVAL; 779*3ee47cadSRui Miguel Silva 780*3ee47cadSRui Miguel Silva fse->min_width = ov2680_mode_data[index].width; 781*3ee47cadSRui Miguel Silva fse->min_height = ov2680_mode_data[index].height; 782*3ee47cadSRui Miguel Silva fse->max_width = ov2680_mode_data[index].width; 783*3ee47cadSRui Miguel Silva fse->max_height = ov2680_mode_data[index].height; 784*3ee47cadSRui Miguel Silva 785*3ee47cadSRui Miguel Silva return 0; 786*3ee47cadSRui Miguel Silva } 787*3ee47cadSRui Miguel Silva 788*3ee47cadSRui Miguel Silva static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, 789*3ee47cadSRui Miguel Silva struct v4l2_subdev_pad_config *cfg, 790*3ee47cadSRui Miguel Silva struct v4l2_subdev_frame_interval_enum *fie) 791*3ee47cadSRui Miguel Silva { 792*3ee47cadSRui Miguel Silva struct v4l2_fract tpf; 793*3ee47cadSRui Miguel Silva 794*3ee47cadSRui Miguel Silva if (fie->index >= OV2680_MODE_MAX || fie->width > OV2680_WIDTH_MAX || 795*3ee47cadSRui Miguel Silva fie->height > OV2680_HEIGHT_MAX || 796*3ee47cadSRui Miguel Silva fie->which > V4L2_SUBDEV_FORMAT_ACTIVE) 797*3ee47cadSRui Miguel Silva return -EINVAL; 798*3ee47cadSRui Miguel Silva 799*3ee47cadSRui Miguel Silva tpf.denominator = OV2680_FRAME_RATE; 800*3ee47cadSRui Miguel Silva tpf.numerator = 1; 801*3ee47cadSRui Miguel Silva 802*3ee47cadSRui Miguel Silva fie->interval = tpf; 803*3ee47cadSRui Miguel Silva 804*3ee47cadSRui Miguel Silva return 0; 805*3ee47cadSRui Miguel Silva } 806*3ee47cadSRui Miguel Silva 807*3ee47cadSRui Miguel Silva static int ov2680_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 808*3ee47cadSRui Miguel Silva { 809*3ee47cadSRui Miguel Silva struct v4l2_subdev *sd = ctrl_to_sd(ctrl); 810*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 811*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 812*3ee47cadSRui Miguel Silva int val; 813*3ee47cadSRui Miguel Silva 814*3ee47cadSRui Miguel Silva if (!sensor->is_enabled) 815*3ee47cadSRui Miguel Silva return 0; 816*3ee47cadSRui Miguel Silva 817*3ee47cadSRui Miguel Silva switch (ctrl->id) { 818*3ee47cadSRui Miguel Silva case V4L2_CID_GAIN: 819*3ee47cadSRui Miguel Silva val = ov2680_gain_get(sensor); 820*3ee47cadSRui Miguel Silva if (val < 0) 821*3ee47cadSRui Miguel Silva return val; 822*3ee47cadSRui Miguel Silva ctrls->gain->val = val; 823*3ee47cadSRui Miguel Silva break; 824*3ee47cadSRui Miguel Silva case V4L2_CID_EXPOSURE: 825*3ee47cadSRui Miguel Silva val = ov2680_exposure_get(sensor); 826*3ee47cadSRui Miguel Silva if (val < 0) 827*3ee47cadSRui Miguel Silva return val; 828*3ee47cadSRui Miguel Silva ctrls->exposure->val = val; 829*3ee47cadSRui Miguel Silva break; 830*3ee47cadSRui Miguel Silva } 831*3ee47cadSRui Miguel Silva 832*3ee47cadSRui Miguel Silva return 0; 833*3ee47cadSRui Miguel Silva } 834*3ee47cadSRui Miguel Silva 835*3ee47cadSRui Miguel Silva static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) 836*3ee47cadSRui Miguel Silva { 837*3ee47cadSRui Miguel Silva struct v4l2_subdev *sd = ctrl_to_sd(ctrl); 838*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 839*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 840*3ee47cadSRui Miguel Silva 841*3ee47cadSRui Miguel Silva if (!sensor->is_enabled) 842*3ee47cadSRui Miguel Silva return 0; 843*3ee47cadSRui Miguel Silva 844*3ee47cadSRui Miguel Silva switch (ctrl->id) { 845*3ee47cadSRui Miguel Silva case V4L2_CID_AUTOGAIN: 846*3ee47cadSRui Miguel Silva return ov2680_gain_set(sensor, !!ctrl->val); 847*3ee47cadSRui Miguel Silva case V4L2_CID_GAIN: 848*3ee47cadSRui Miguel Silva return ov2680_gain_set(sensor, !!ctrls->auto_gain->val); 849*3ee47cadSRui Miguel Silva case V4L2_CID_EXPOSURE_AUTO: 850*3ee47cadSRui Miguel Silva return ov2680_exposure_set(sensor, !!ctrl->val); 851*3ee47cadSRui Miguel Silva case V4L2_CID_EXPOSURE: 852*3ee47cadSRui Miguel Silva return ov2680_exposure_set(sensor, !!ctrls->auto_exp->val); 853*3ee47cadSRui Miguel Silva case V4L2_CID_VFLIP: 854*3ee47cadSRui Miguel Silva if (sensor->is_streaming) 855*3ee47cadSRui Miguel Silva return -EBUSY; 856*3ee47cadSRui Miguel Silva if (ctrl->val) 857*3ee47cadSRui Miguel Silva return ov2680_vflip_enable(sensor); 858*3ee47cadSRui Miguel Silva else 859*3ee47cadSRui Miguel Silva return ov2680_vflip_disable(sensor); 860*3ee47cadSRui Miguel Silva case V4L2_CID_HFLIP: 861*3ee47cadSRui Miguel Silva if (sensor->is_streaming) 862*3ee47cadSRui Miguel Silva return -EBUSY; 863*3ee47cadSRui Miguel Silva if (ctrl->val) 864*3ee47cadSRui Miguel Silva return ov2680_hflip_enable(sensor); 865*3ee47cadSRui Miguel Silva else 866*3ee47cadSRui Miguel Silva return ov2680_hflip_disable(sensor); 867*3ee47cadSRui Miguel Silva case V4L2_CID_TEST_PATTERN: 868*3ee47cadSRui Miguel Silva return ov2680_test_pattern_set(sensor, ctrl->val); 869*3ee47cadSRui Miguel Silva default: 870*3ee47cadSRui Miguel Silva break; 871*3ee47cadSRui Miguel Silva } 872*3ee47cadSRui Miguel Silva 873*3ee47cadSRui Miguel Silva return -EINVAL; 874*3ee47cadSRui Miguel Silva } 875*3ee47cadSRui Miguel Silva 876*3ee47cadSRui Miguel Silva static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { 877*3ee47cadSRui Miguel Silva .g_volatile_ctrl = ov2680_g_volatile_ctrl, 878*3ee47cadSRui Miguel Silva .s_ctrl = ov2680_s_ctrl, 879*3ee47cadSRui Miguel Silva }; 880*3ee47cadSRui Miguel Silva 881*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_core_ops ov2680_core_ops = { 882*3ee47cadSRui Miguel Silva .s_power = ov2680_s_power, 883*3ee47cadSRui Miguel Silva }; 884*3ee47cadSRui Miguel Silva 885*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_video_ops ov2680_video_ops = { 886*3ee47cadSRui Miguel Silva .g_frame_interval = ov2680_s_g_frame_interval, 887*3ee47cadSRui Miguel Silva .s_frame_interval = ov2680_s_g_frame_interval, 888*3ee47cadSRui Miguel Silva .s_stream = ov2680_s_stream, 889*3ee47cadSRui Miguel Silva }; 890*3ee47cadSRui Miguel Silva 891*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { 892*3ee47cadSRui Miguel Silva .init_cfg = ov2680_init_cfg, 893*3ee47cadSRui Miguel Silva .enum_mbus_code = ov2680_enum_mbus_code, 894*3ee47cadSRui Miguel Silva .get_fmt = ov2680_get_fmt, 895*3ee47cadSRui Miguel Silva .set_fmt = ov2680_set_fmt, 896*3ee47cadSRui Miguel Silva .enum_frame_size = ov2680_enum_frame_size, 897*3ee47cadSRui Miguel Silva .enum_frame_interval = ov2680_enum_frame_interval, 898*3ee47cadSRui Miguel Silva }; 899*3ee47cadSRui Miguel Silva 900*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_ops ov2680_subdev_ops = { 901*3ee47cadSRui Miguel Silva .core = &ov2680_core_ops, 902*3ee47cadSRui Miguel Silva .video = &ov2680_video_ops, 903*3ee47cadSRui Miguel Silva .pad = &ov2680_pad_ops, 904*3ee47cadSRui Miguel Silva }; 905*3ee47cadSRui Miguel Silva 906*3ee47cadSRui Miguel Silva static int ov2680_mode_init(struct ov2680_dev *sensor) 907*3ee47cadSRui Miguel Silva { 908*3ee47cadSRui Miguel Silva const struct ov2680_mode_info *init_mode; 909*3ee47cadSRui Miguel Silva 910*3ee47cadSRui Miguel Silva /* set initial mode */ 911*3ee47cadSRui Miguel Silva sensor->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; 912*3ee47cadSRui Miguel Silva sensor->fmt.width = 800; 913*3ee47cadSRui Miguel Silva sensor->fmt.height = 600; 914*3ee47cadSRui Miguel Silva sensor->fmt.field = V4L2_FIELD_NONE; 915*3ee47cadSRui Miguel Silva sensor->fmt.colorspace = V4L2_COLORSPACE_SRGB; 916*3ee47cadSRui Miguel Silva 917*3ee47cadSRui Miguel Silva sensor->frame_interval.denominator = OV2680_FRAME_RATE; 918*3ee47cadSRui Miguel Silva sensor->frame_interval.numerator = 1; 919*3ee47cadSRui Miguel Silva 920*3ee47cadSRui Miguel Silva init_mode = &ov2680_mode_init_data; 921*3ee47cadSRui Miguel Silva 922*3ee47cadSRui Miguel Silva sensor->current_mode = init_mode; 923*3ee47cadSRui Miguel Silva 924*3ee47cadSRui Miguel Silva sensor->mode_pending_changes = true; 925*3ee47cadSRui Miguel Silva 926*3ee47cadSRui Miguel Silva return 0; 927*3ee47cadSRui Miguel Silva } 928*3ee47cadSRui Miguel Silva 929*3ee47cadSRui Miguel Silva static int ov2680_v4l2_init(struct ov2680_dev *sensor) 930*3ee47cadSRui Miguel Silva { 931*3ee47cadSRui Miguel Silva const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops; 932*3ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 933*3ee47cadSRui Miguel Silva struct v4l2_ctrl_handler *hdl = &ctrls->handler; 934*3ee47cadSRui Miguel Silva int ret = 0; 935*3ee47cadSRui Miguel Silva 936*3ee47cadSRui Miguel Silva v4l2_i2c_subdev_init(&sensor->sd, sensor->i2c_client, 937*3ee47cadSRui Miguel Silva &ov2680_subdev_ops); 938*3ee47cadSRui Miguel Silva 939*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 940*3ee47cadSRui Miguel Silva sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 941*3ee47cadSRui Miguel Silva #endif 942*3ee47cadSRui Miguel Silva sensor->pad.flags = MEDIA_PAD_FL_SOURCE; 943*3ee47cadSRui Miguel Silva sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 944*3ee47cadSRui Miguel Silva 945*3ee47cadSRui Miguel Silva ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); 946*3ee47cadSRui Miguel Silva if (ret < 0) 947*3ee47cadSRui Miguel Silva return ret; 948*3ee47cadSRui Miguel Silva 949*3ee47cadSRui Miguel Silva v4l2_ctrl_handler_init(hdl, 7); 950*3ee47cadSRui Miguel Silva 951*3ee47cadSRui Miguel Silva hdl->lock = &sensor->lock; 952*3ee47cadSRui Miguel Silva 953*3ee47cadSRui Miguel Silva ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); 954*3ee47cadSRui Miguel Silva ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); 955*3ee47cadSRui Miguel Silva 956*3ee47cadSRui Miguel Silva ctrls->test_pattern = v4l2_ctrl_new_std_menu_items(hdl, 957*3ee47cadSRui Miguel Silva &ov2680_ctrl_ops, V4L2_CID_TEST_PATTERN, 958*3ee47cadSRui Miguel Silva ARRAY_SIZE(test_pattern_menu) - 1, 959*3ee47cadSRui Miguel Silva 0, 0, test_pattern_menu); 960*3ee47cadSRui Miguel Silva 961*3ee47cadSRui Miguel Silva ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops, 962*3ee47cadSRui Miguel Silva V4L2_CID_EXPOSURE_AUTO, 963*3ee47cadSRui Miguel Silva V4L2_EXPOSURE_MANUAL, 0, 964*3ee47cadSRui Miguel Silva V4L2_EXPOSURE_AUTO); 965*3ee47cadSRui Miguel Silva 966*3ee47cadSRui Miguel Silva ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, 967*3ee47cadSRui Miguel Silva 0, 32767, 1, 0); 968*3ee47cadSRui Miguel Silva 969*3ee47cadSRui Miguel Silva ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN, 970*3ee47cadSRui Miguel Silva 0, 1, 1, 1); 971*3ee47cadSRui Miguel Silva ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 2047, 1, 0); 972*3ee47cadSRui Miguel Silva 973*3ee47cadSRui Miguel Silva if (hdl->error) { 974*3ee47cadSRui Miguel Silva ret = hdl->error; 975*3ee47cadSRui Miguel Silva goto cleanup_entity; 976*3ee47cadSRui Miguel Silva } 977*3ee47cadSRui Miguel Silva 978*3ee47cadSRui Miguel Silva ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE; 979*3ee47cadSRui Miguel Silva ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; 980*3ee47cadSRui Miguel Silva 981*3ee47cadSRui Miguel Silva v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true); 982*3ee47cadSRui Miguel Silva v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true); 983*3ee47cadSRui Miguel Silva 984*3ee47cadSRui Miguel Silva sensor->sd.ctrl_handler = hdl; 985*3ee47cadSRui Miguel Silva 986*3ee47cadSRui Miguel Silva ret = v4l2_async_register_subdev(&sensor->sd); 987*3ee47cadSRui Miguel Silva if (ret < 0) 988*3ee47cadSRui Miguel Silva goto cleanup_entity; 989*3ee47cadSRui Miguel Silva 990*3ee47cadSRui Miguel Silva return 0; 991*3ee47cadSRui Miguel Silva 992*3ee47cadSRui Miguel Silva cleanup_entity: 993*3ee47cadSRui Miguel Silva media_entity_cleanup(&sensor->sd.entity); 994*3ee47cadSRui Miguel Silva v4l2_ctrl_handler_free(hdl); 995*3ee47cadSRui Miguel Silva 996*3ee47cadSRui Miguel Silva return ret; 997*3ee47cadSRui Miguel Silva } 998*3ee47cadSRui Miguel Silva 999*3ee47cadSRui Miguel Silva static int ov2680_get_regulators(struct ov2680_dev *sensor) 1000*3ee47cadSRui Miguel Silva { 1001*3ee47cadSRui Miguel Silva int i; 1002*3ee47cadSRui Miguel Silva 1003*3ee47cadSRui Miguel Silva for (i = 0; i < OV2680_NUM_SUPPLIES; i++) 1004*3ee47cadSRui Miguel Silva sensor->supplies[i].supply = ov2680_supply_name[i]; 1005*3ee47cadSRui Miguel Silva 1006*3ee47cadSRui Miguel Silva return devm_regulator_bulk_get(&sensor->i2c_client->dev, 1007*3ee47cadSRui Miguel Silva OV2680_NUM_SUPPLIES, 1008*3ee47cadSRui Miguel Silva sensor->supplies); 1009*3ee47cadSRui Miguel Silva } 1010*3ee47cadSRui Miguel Silva 1011*3ee47cadSRui Miguel Silva static int ov2680_check_id(struct ov2680_dev *sensor) 1012*3ee47cadSRui Miguel Silva { 1013*3ee47cadSRui Miguel Silva struct device *dev = ov2680_to_dev(sensor); 1014*3ee47cadSRui Miguel Silva u32 chip_id; 1015*3ee47cadSRui Miguel Silva int ret; 1016*3ee47cadSRui Miguel Silva 1017*3ee47cadSRui Miguel Silva ov2680_power_on(sensor); 1018*3ee47cadSRui Miguel Silva 1019*3ee47cadSRui Miguel Silva ret = ov2680_read_reg16(sensor, OV2680_REG_CHIP_ID_HIGH, &chip_id); 1020*3ee47cadSRui Miguel Silva if (ret < 0) { 1021*3ee47cadSRui Miguel Silva dev_err(dev, "failed to read chip id high\n"); 1022*3ee47cadSRui Miguel Silva return -ENODEV; 1023*3ee47cadSRui Miguel Silva } 1024*3ee47cadSRui Miguel Silva 1025*3ee47cadSRui Miguel Silva if (chip_id != OV2680_CHIP_ID) { 1026*3ee47cadSRui Miguel Silva dev_err(dev, "chip id: 0x%04x does not match expected 0x%04x\n", 1027*3ee47cadSRui Miguel Silva chip_id, OV2680_CHIP_ID); 1028*3ee47cadSRui Miguel Silva return -ENODEV; 1029*3ee47cadSRui Miguel Silva } 1030*3ee47cadSRui Miguel Silva 1031*3ee47cadSRui Miguel Silva return 0; 1032*3ee47cadSRui Miguel Silva } 1033*3ee47cadSRui Miguel Silva 1034*3ee47cadSRui Miguel Silva static int ov2860_parse_dt(struct ov2680_dev *sensor) 1035*3ee47cadSRui Miguel Silva { 1036*3ee47cadSRui Miguel Silva struct device *dev = ov2680_to_dev(sensor); 1037*3ee47cadSRui Miguel Silva int ret; 1038*3ee47cadSRui Miguel Silva 1039*3ee47cadSRui Miguel Silva sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset", 1040*3ee47cadSRui Miguel Silva GPIOD_OUT_HIGH); 1041*3ee47cadSRui Miguel Silva ret = PTR_ERR_OR_ZERO(sensor->reset_gpio); 1042*3ee47cadSRui Miguel Silva if (ret < 0) { 1043*3ee47cadSRui Miguel Silva dev_dbg(dev, "error while getting reset gpio: %d\n", ret); 1044*3ee47cadSRui Miguel Silva return ret; 1045*3ee47cadSRui Miguel Silva } 1046*3ee47cadSRui Miguel Silva 1047*3ee47cadSRui Miguel Silva sensor->xvclk = devm_clk_get(dev, "xvclk"); 1048*3ee47cadSRui Miguel Silva if (IS_ERR(sensor->xvclk)) { 1049*3ee47cadSRui Miguel Silva dev_err(dev, "xvclk clock missing or invalid\n"); 1050*3ee47cadSRui Miguel Silva return PTR_ERR(sensor->xvclk); 1051*3ee47cadSRui Miguel Silva } 1052*3ee47cadSRui Miguel Silva 1053*3ee47cadSRui Miguel Silva sensor->xvclk_freq = clk_get_rate(sensor->xvclk); 1054*3ee47cadSRui Miguel Silva if (sensor->xvclk_freq != OV2680_XVCLK_VALUE) { 1055*3ee47cadSRui Miguel Silva dev_err(dev, "wrong xvclk frequency %d HZ, expected: %d Hz\n", 1056*3ee47cadSRui Miguel Silva sensor->xvclk_freq, OV2680_XVCLK_VALUE); 1057*3ee47cadSRui Miguel Silva return -EINVAL; 1058*3ee47cadSRui Miguel Silva } 1059*3ee47cadSRui Miguel Silva 1060*3ee47cadSRui Miguel Silva return 0; 1061*3ee47cadSRui Miguel Silva } 1062*3ee47cadSRui Miguel Silva 1063*3ee47cadSRui Miguel Silva static int ov2680_probe(struct i2c_client *client) 1064*3ee47cadSRui Miguel Silva { 1065*3ee47cadSRui Miguel Silva struct device *dev = &client->dev; 1066*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor; 1067*3ee47cadSRui Miguel Silva int ret; 1068*3ee47cadSRui Miguel Silva 1069*3ee47cadSRui Miguel Silva sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); 1070*3ee47cadSRui Miguel Silva if (!sensor) 1071*3ee47cadSRui Miguel Silva return -ENOMEM; 1072*3ee47cadSRui Miguel Silva 1073*3ee47cadSRui Miguel Silva sensor->i2c_client = client; 1074*3ee47cadSRui Miguel Silva 1075*3ee47cadSRui Miguel Silva ret = ov2860_parse_dt(sensor); 1076*3ee47cadSRui Miguel Silva if (ret < 0) 1077*3ee47cadSRui Miguel Silva return -EINVAL; 1078*3ee47cadSRui Miguel Silva 1079*3ee47cadSRui Miguel Silva ret = ov2680_mode_init(sensor); 1080*3ee47cadSRui Miguel Silva if (ret < 0) 1081*3ee47cadSRui Miguel Silva return ret; 1082*3ee47cadSRui Miguel Silva 1083*3ee47cadSRui Miguel Silva ret = ov2680_get_regulators(sensor); 1084*3ee47cadSRui Miguel Silva if (ret < 0) { 1085*3ee47cadSRui Miguel Silva dev_err(dev, "failed to get regulators\n"); 1086*3ee47cadSRui Miguel Silva return ret; 1087*3ee47cadSRui Miguel Silva } 1088*3ee47cadSRui Miguel Silva 1089*3ee47cadSRui Miguel Silva mutex_init(&sensor->lock); 1090*3ee47cadSRui Miguel Silva 1091*3ee47cadSRui Miguel Silva ret = ov2680_v4l2_init(sensor); 1092*3ee47cadSRui Miguel Silva if (ret < 0) 1093*3ee47cadSRui Miguel Silva goto lock_destroy; 1094*3ee47cadSRui Miguel Silva 1095*3ee47cadSRui Miguel Silva ret = ov2680_check_id(sensor); 1096*3ee47cadSRui Miguel Silva if (ret < 0) 1097*3ee47cadSRui Miguel Silva goto error_cleanup; 1098*3ee47cadSRui Miguel Silva 1099*3ee47cadSRui Miguel Silva dev_info(dev, "ov2680 init correctly\n"); 1100*3ee47cadSRui Miguel Silva 1101*3ee47cadSRui Miguel Silva return 0; 1102*3ee47cadSRui Miguel Silva 1103*3ee47cadSRui Miguel Silva error_cleanup: 1104*3ee47cadSRui Miguel Silva dev_err(dev, "ov2680 init fail: %d\n", ret); 1105*3ee47cadSRui Miguel Silva 1106*3ee47cadSRui Miguel Silva media_entity_cleanup(&sensor->sd.entity); 1107*3ee47cadSRui Miguel Silva v4l2_async_unregister_subdev(&sensor->sd); 1108*3ee47cadSRui Miguel Silva v4l2_ctrl_handler_free(&sensor->ctrls.handler); 1109*3ee47cadSRui Miguel Silva 1110*3ee47cadSRui Miguel Silva lock_destroy: 1111*3ee47cadSRui Miguel Silva mutex_destroy(&sensor->lock); 1112*3ee47cadSRui Miguel Silva 1113*3ee47cadSRui Miguel Silva return ret; 1114*3ee47cadSRui Miguel Silva } 1115*3ee47cadSRui Miguel Silva 1116*3ee47cadSRui Miguel Silva static int ov2680_remove(struct i2c_client *client) 1117*3ee47cadSRui Miguel Silva { 1118*3ee47cadSRui Miguel Silva struct v4l2_subdev *sd = i2c_get_clientdata(client); 1119*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 1120*3ee47cadSRui Miguel Silva 1121*3ee47cadSRui Miguel Silva v4l2_async_unregister_subdev(&sensor->sd); 1122*3ee47cadSRui Miguel Silva mutex_destroy(&sensor->lock); 1123*3ee47cadSRui Miguel Silva media_entity_cleanup(&sensor->sd.entity); 1124*3ee47cadSRui Miguel Silva v4l2_ctrl_handler_free(&sensor->ctrls.handler); 1125*3ee47cadSRui Miguel Silva 1126*3ee47cadSRui Miguel Silva return 0; 1127*3ee47cadSRui Miguel Silva } 1128*3ee47cadSRui Miguel Silva 1129*3ee47cadSRui Miguel Silva static int __maybe_unused ov2680_suspend(struct device *dev) 1130*3ee47cadSRui Miguel Silva { 1131*3ee47cadSRui Miguel Silva struct i2c_client *client = to_i2c_client(dev); 1132*3ee47cadSRui Miguel Silva struct v4l2_subdev *sd = i2c_get_clientdata(client); 1133*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 1134*3ee47cadSRui Miguel Silva 1135*3ee47cadSRui Miguel Silva if (sensor->is_streaming) 1136*3ee47cadSRui Miguel Silva ov2680_stream_disable(sensor); 1137*3ee47cadSRui Miguel Silva 1138*3ee47cadSRui Miguel Silva return 0; 1139*3ee47cadSRui Miguel Silva } 1140*3ee47cadSRui Miguel Silva 1141*3ee47cadSRui Miguel Silva static int __maybe_unused ov2680_resume(struct device *dev) 1142*3ee47cadSRui Miguel Silva { 1143*3ee47cadSRui Miguel Silva struct i2c_client *client = to_i2c_client(dev); 1144*3ee47cadSRui Miguel Silva struct v4l2_subdev *sd = i2c_get_clientdata(client); 1145*3ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 1146*3ee47cadSRui Miguel Silva int ret; 1147*3ee47cadSRui Miguel Silva 1148*3ee47cadSRui Miguel Silva if (sensor->is_streaming) { 1149*3ee47cadSRui Miguel Silva ret = ov2680_stream_enable(sensor); 1150*3ee47cadSRui Miguel Silva if (ret < 0) 1151*3ee47cadSRui Miguel Silva goto stream_disable; 1152*3ee47cadSRui Miguel Silva } 1153*3ee47cadSRui Miguel Silva 1154*3ee47cadSRui Miguel Silva return 0; 1155*3ee47cadSRui Miguel Silva 1156*3ee47cadSRui Miguel Silva stream_disable: 1157*3ee47cadSRui Miguel Silva ov2680_stream_disable(sensor); 1158*3ee47cadSRui Miguel Silva sensor->is_streaming = false; 1159*3ee47cadSRui Miguel Silva 1160*3ee47cadSRui Miguel Silva return ret; 1161*3ee47cadSRui Miguel Silva } 1162*3ee47cadSRui Miguel Silva 1163*3ee47cadSRui Miguel Silva static const struct dev_pm_ops ov2680_pm_ops = { 1164*3ee47cadSRui Miguel Silva SET_SYSTEM_SLEEP_PM_OPS(ov2680_suspend, ov2680_resume) 1165*3ee47cadSRui Miguel Silva }; 1166*3ee47cadSRui Miguel Silva 1167*3ee47cadSRui Miguel Silva static const struct of_device_id ov2680_dt_ids[] = { 1168*3ee47cadSRui Miguel Silva { .compatible = "ovti,ov2680" }, 1169*3ee47cadSRui Miguel Silva { /* sentinel */ }, 1170*3ee47cadSRui Miguel Silva }; 1171*3ee47cadSRui Miguel Silva MODULE_DEVICE_TABLE(of, ov2680_dt_ids); 1172*3ee47cadSRui Miguel Silva 1173*3ee47cadSRui Miguel Silva static struct i2c_driver ov2680_i2c_driver = { 1174*3ee47cadSRui Miguel Silva .driver = { 1175*3ee47cadSRui Miguel Silva .name = "ov2680", 1176*3ee47cadSRui Miguel Silva .pm = &ov2680_pm_ops, 1177*3ee47cadSRui Miguel Silva .of_match_table = of_match_ptr(ov2680_dt_ids), 1178*3ee47cadSRui Miguel Silva }, 1179*3ee47cadSRui Miguel Silva .probe_new = ov2680_probe, 1180*3ee47cadSRui Miguel Silva .remove = ov2680_remove, 1181*3ee47cadSRui Miguel Silva }; 1182*3ee47cadSRui Miguel Silva module_i2c_driver(ov2680_i2c_driver); 1183*3ee47cadSRui Miguel Silva 1184*3ee47cadSRui Miguel Silva MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>"); 1185*3ee47cadSRui Miguel Silva MODULE_DESCRIPTION("OV2680 CMOS Image Sensor driver"); 1186*3ee47cadSRui Miguel Silva MODULE_LICENSE("GPL v2"); 1187