1e3861d91SShunqian Zheng // SPDX-License-Identifier: GPL-2.0 2e3861d91SShunqian Zheng /* 3e3861d91SShunqian Zheng * ov2685 driver 4e3861d91SShunqian Zheng * 5e3861d91SShunqian Zheng * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. 6e3861d91SShunqian Zheng */ 7e3861d91SShunqian Zheng 8e3861d91SShunqian Zheng #include <linux/clk.h> 9e3861d91SShunqian Zheng #include <linux/device.h> 10e3861d91SShunqian Zheng #include <linux/delay.h> 11e3861d91SShunqian Zheng #include <linux/gpio/consumer.h> 12e3861d91SShunqian Zheng #include <linux/i2c.h> 13e3861d91SShunqian Zheng #include <linux/module.h> 14e3861d91SShunqian Zheng #include <linux/pm_runtime.h> 15e3861d91SShunqian Zheng #include <linux/regulator/consumer.h> 16e3861d91SShunqian Zheng #include <linux/sysfs.h> 17e3861d91SShunqian Zheng #include <media/media-entity.h> 18e3861d91SShunqian Zheng #include <media/v4l2-async.h> 19e3861d91SShunqian Zheng #include <media/v4l2-ctrls.h> 20e3861d91SShunqian Zheng #include <media/v4l2-subdev.h> 21e3861d91SShunqian Zheng 22e3861d91SShunqian Zheng #define CHIP_ID 0x2685 23e3861d91SShunqian Zheng #define OV2685_REG_CHIP_ID 0x300a 24e3861d91SShunqian Zheng 25e3861d91SShunqian Zheng #define OV2685_XVCLK_FREQ 24000000 26e3861d91SShunqian Zheng 27e3861d91SShunqian Zheng #define REG_SC_CTRL_MODE 0x0100 28e3861d91SShunqian Zheng #define SC_CTRL_MODE_STANDBY 0x0 29e3861d91SShunqian Zheng #define SC_CTRL_MODE_STREAMING BIT(0) 30e3861d91SShunqian Zheng 31e3861d91SShunqian Zheng #define OV2685_REG_EXPOSURE 0x3500 32e3861d91SShunqian Zheng #define OV2685_EXPOSURE_MIN 4 33e3861d91SShunqian Zheng #define OV2685_EXPOSURE_STEP 1 34e3861d91SShunqian Zheng 35e3861d91SShunqian Zheng #define OV2685_REG_VTS 0x380e 36e3861d91SShunqian Zheng #define OV2685_VTS_MAX 0x7fff 37e3861d91SShunqian Zheng 38e3861d91SShunqian Zheng #define OV2685_REG_GAIN 0x350a 39e3861d91SShunqian Zheng #define OV2685_GAIN_MIN 0 40e3861d91SShunqian Zheng #define OV2685_GAIN_MAX 0x07ff 41e3861d91SShunqian Zheng #define OV2685_GAIN_STEP 0x1 42e3861d91SShunqian Zheng #define OV2685_GAIN_DEFAULT 0x0036 43e3861d91SShunqian Zheng 44e3861d91SShunqian Zheng #define OV2685_REG_TEST_PATTERN 0x5080 45e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_DISABLED 0x00 46e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_COLOR_BAR 0x80 47e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_RANDOM 0x81 48e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_COLOR_BAR_FADE 0x88 49e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_BW_SQUARE 0x92 50e3861d91SShunqian Zheng #define OV2685_TEST_PATTERN_COLOR_SQUARE 0x82 51e3861d91SShunqian Zheng 52e3861d91SShunqian Zheng #define REG_NULL 0xFFFF 53e3861d91SShunqian Zheng 54e3861d91SShunqian Zheng #define OV2685_REG_VALUE_08BIT 1 55e3861d91SShunqian Zheng #define OV2685_REG_VALUE_16BIT 2 56e3861d91SShunqian Zheng #define OV2685_REG_VALUE_24BIT 3 57e3861d91SShunqian Zheng 58e3861d91SShunqian Zheng #define OV2685_LANES 1 59e3861d91SShunqian Zheng #define OV2685_BITS_PER_SAMPLE 10 60e3861d91SShunqian Zheng 61e3861d91SShunqian Zheng static const char * const ov2685_supply_names[] = { 62e3861d91SShunqian Zheng "avdd", /* Analog power */ 63e3861d91SShunqian Zheng "dovdd", /* Digital I/O power */ 64e3861d91SShunqian Zheng "dvdd", /* Digital core power */ 65e3861d91SShunqian Zheng }; 66e3861d91SShunqian Zheng 67e3861d91SShunqian Zheng #define OV2685_NUM_SUPPLIES ARRAY_SIZE(ov2685_supply_names) 68e3861d91SShunqian Zheng 69e3861d91SShunqian Zheng struct regval { 70e3861d91SShunqian Zheng u16 addr; 71e3861d91SShunqian Zheng u8 val; 72e3861d91SShunqian Zheng }; 73e3861d91SShunqian Zheng 74e3861d91SShunqian Zheng struct ov2685_mode { 75e3861d91SShunqian Zheng u32 width; 76e3861d91SShunqian Zheng u32 height; 77e3861d91SShunqian Zheng u32 exp_def; 78e3861d91SShunqian Zheng u32 hts_def; 79e3861d91SShunqian Zheng u32 vts_def; 80e3861d91SShunqian Zheng const struct regval *reg_list; 81e3861d91SShunqian Zheng }; 82e3861d91SShunqian Zheng 83e3861d91SShunqian Zheng struct ov2685 { 84e3861d91SShunqian Zheng struct i2c_client *client; 85e3861d91SShunqian Zheng struct clk *xvclk; 86e3861d91SShunqian Zheng struct gpio_desc *reset_gpio; 87e3861d91SShunqian Zheng struct regulator_bulk_data supplies[OV2685_NUM_SUPPLIES]; 88e3861d91SShunqian Zheng 89e3861d91SShunqian Zheng bool streaming; 90e3861d91SShunqian Zheng struct mutex mutex; 91e3861d91SShunqian Zheng struct v4l2_subdev subdev; 92e3861d91SShunqian Zheng struct media_pad pad; 93e3861d91SShunqian Zheng struct v4l2_ctrl *anal_gain; 94e3861d91SShunqian Zheng struct v4l2_ctrl *exposure; 95e3861d91SShunqian Zheng struct v4l2_ctrl *hblank; 96e3861d91SShunqian Zheng struct v4l2_ctrl *vblank; 97e3861d91SShunqian Zheng struct v4l2_ctrl *test_pattern; 98e3861d91SShunqian Zheng struct v4l2_ctrl_handler ctrl_handler; 99e3861d91SShunqian Zheng 100e3861d91SShunqian Zheng const struct ov2685_mode *cur_mode; 101e3861d91SShunqian Zheng }; 102e3861d91SShunqian Zheng 103e3861d91SShunqian Zheng #define to_ov2685(sd) container_of(sd, struct ov2685, subdev) 104e3861d91SShunqian Zheng 105e3861d91SShunqian Zheng /* PLL settings bases on 24M xvclk */ 106e3861d91SShunqian Zheng static struct regval ov2685_1600x1200_regs[] = { 107e3861d91SShunqian Zheng {0x0103, 0x01}, 108e3861d91SShunqian Zheng {0x0100, 0x00}, 109e3861d91SShunqian Zheng {0x3002, 0x00}, 110e3861d91SShunqian Zheng {0x3016, 0x1c}, 111e3861d91SShunqian Zheng {0x3018, 0x44}, 112e3861d91SShunqian Zheng {0x301d, 0xf0}, 113e3861d91SShunqian Zheng {0x3020, 0x00}, 114e3861d91SShunqian Zheng {0x3082, 0x37}, 115e3861d91SShunqian Zheng {0x3083, 0x03}, 116e3861d91SShunqian Zheng {0x3084, 0x09}, 117e3861d91SShunqian Zheng {0x3085, 0x04}, 118e3861d91SShunqian Zheng {0x3086, 0x00}, 119e3861d91SShunqian Zheng {0x3087, 0x00}, 120e3861d91SShunqian Zheng {0x3501, 0x4e}, 121e3861d91SShunqian Zheng {0x3502, 0xe0}, 122e3861d91SShunqian Zheng {0x3503, 0x07}, 123e3861d91SShunqian Zheng {0x350b, 0x36}, 124e3861d91SShunqian Zheng {0x3600, 0xb4}, 125e3861d91SShunqian Zheng {0x3603, 0x35}, 126e3861d91SShunqian Zheng {0x3604, 0x24}, 127e3861d91SShunqian Zheng {0x3605, 0x00}, 128e3861d91SShunqian Zheng {0x3620, 0x24}, 129e3861d91SShunqian Zheng {0x3621, 0x34}, 130e3861d91SShunqian Zheng {0x3622, 0x03}, 131e3861d91SShunqian Zheng {0x3628, 0x10}, 132e3861d91SShunqian Zheng {0x3705, 0x3c}, 133e3861d91SShunqian Zheng {0x370a, 0x21}, 134e3861d91SShunqian Zheng {0x370c, 0x50}, 135e3861d91SShunqian Zheng {0x370d, 0xc0}, 136e3861d91SShunqian Zheng {0x3717, 0x58}, 137e3861d91SShunqian Zheng {0x3718, 0x80}, 138e3861d91SShunqian Zheng {0x3720, 0x00}, 139e3861d91SShunqian Zheng {0x3721, 0x09}, 140e3861d91SShunqian Zheng {0x3722, 0x06}, 141e3861d91SShunqian Zheng {0x3723, 0x59}, 142e3861d91SShunqian Zheng {0x3738, 0x99}, 143e3861d91SShunqian Zheng {0x3781, 0x80}, 144e3861d91SShunqian Zheng {0x3784, 0x0c}, 145e3861d91SShunqian Zheng {0x3789, 0x60}, 146e3861d91SShunqian Zheng {0x3800, 0x00}, 147e3861d91SShunqian Zheng {0x3801, 0x00}, 148e3861d91SShunqian Zheng {0x3802, 0x00}, 149e3861d91SShunqian Zheng {0x3803, 0x00}, 150e3861d91SShunqian Zheng {0x3804, 0x06}, 151e3861d91SShunqian Zheng {0x3805, 0x4f}, 152e3861d91SShunqian Zheng {0x3806, 0x04}, 153e3861d91SShunqian Zheng {0x3807, 0xbf}, 154e3861d91SShunqian Zheng {0x3808, 0x06}, 155e3861d91SShunqian Zheng {0x3809, 0x40}, 156e3861d91SShunqian Zheng {0x380a, 0x04}, 157e3861d91SShunqian Zheng {0x380b, 0xb0}, 158e3861d91SShunqian Zheng {0x380c, 0x06}, 159e3861d91SShunqian Zheng {0x380d, 0xa4}, 160e3861d91SShunqian Zheng {0x380e, 0x05}, 161e3861d91SShunqian Zheng {0x380f, 0x0e}, 162e3861d91SShunqian Zheng {0x3810, 0x00}, 163e3861d91SShunqian Zheng {0x3811, 0x08}, 164e3861d91SShunqian Zheng {0x3812, 0x00}, 165e3861d91SShunqian Zheng {0x3813, 0x08}, 166e3861d91SShunqian Zheng {0x3814, 0x11}, 167e3861d91SShunqian Zheng {0x3815, 0x11}, 168e3861d91SShunqian Zheng {0x3819, 0x04}, 169e3861d91SShunqian Zheng {0x3820, 0xc0}, 170e3861d91SShunqian Zheng {0x3821, 0x00}, 171e3861d91SShunqian Zheng {0x3a06, 0x01}, 172e3861d91SShunqian Zheng {0x3a07, 0x84}, 173e3861d91SShunqian Zheng {0x3a08, 0x01}, 174e3861d91SShunqian Zheng {0x3a09, 0x43}, 175e3861d91SShunqian Zheng {0x3a0a, 0x24}, 176e3861d91SShunqian Zheng {0x3a0b, 0x60}, 177e3861d91SShunqian Zheng {0x3a0c, 0x28}, 178e3861d91SShunqian Zheng {0x3a0d, 0x60}, 179e3861d91SShunqian Zheng {0x3a0e, 0x04}, 180e3861d91SShunqian Zheng {0x3a0f, 0x8c}, 181e3861d91SShunqian Zheng {0x3a10, 0x05}, 182e3861d91SShunqian Zheng {0x3a11, 0x0c}, 183e3861d91SShunqian Zheng {0x4000, 0x81}, 184e3861d91SShunqian Zheng {0x4001, 0x40}, 185e3861d91SShunqian Zheng {0x4008, 0x02}, 186e3861d91SShunqian Zheng {0x4009, 0x09}, 187e3861d91SShunqian Zheng {0x4300, 0x00}, 188e3861d91SShunqian Zheng {0x430e, 0x00}, 189e3861d91SShunqian Zheng {0x4602, 0x02}, 190e3861d91SShunqian Zheng {0x481b, 0x40}, 191e3861d91SShunqian Zheng {0x481f, 0x40}, 192e3861d91SShunqian Zheng {0x4837, 0x18}, 193e3861d91SShunqian Zheng {0x5000, 0x1f}, 194e3861d91SShunqian Zheng {0x5001, 0x05}, 195e3861d91SShunqian Zheng {0x5002, 0x30}, 196e3861d91SShunqian Zheng {0x5003, 0x04}, 197e3861d91SShunqian Zheng {0x5004, 0x00}, 198e3861d91SShunqian Zheng {0x5005, 0x0c}, 199e3861d91SShunqian Zheng {0x5280, 0x15}, 200e3861d91SShunqian Zheng {0x5281, 0x06}, 201e3861d91SShunqian Zheng {0x5282, 0x06}, 202e3861d91SShunqian Zheng {0x5283, 0x08}, 203e3861d91SShunqian Zheng {0x5284, 0x1c}, 204e3861d91SShunqian Zheng {0x5285, 0x1c}, 205e3861d91SShunqian Zheng {0x5286, 0x20}, 206e3861d91SShunqian Zheng {0x5287, 0x10}, 207e3861d91SShunqian Zheng {REG_NULL, 0x00} 208e3861d91SShunqian Zheng }; 209e3861d91SShunqian Zheng 210e3861d91SShunqian Zheng #define OV2685_LINK_FREQ_330MHZ 330000000 211e3861d91SShunqian Zheng static const s64 link_freq_menu_items[] = { 212e3861d91SShunqian Zheng OV2685_LINK_FREQ_330MHZ 213e3861d91SShunqian Zheng }; 214e3861d91SShunqian Zheng 215e3861d91SShunqian Zheng static const char * const ov2685_test_pattern_menu[] = { 216e3861d91SShunqian Zheng "Disabled", 217e3861d91SShunqian Zheng "Color Bar", 218e3861d91SShunqian Zheng "Color Bar FADE", 219e3861d91SShunqian Zheng "Random Data", 220e3861d91SShunqian Zheng "Black White Square", 221e3861d91SShunqian Zheng "Color Square" 222e3861d91SShunqian Zheng }; 223e3861d91SShunqian Zheng 224e3861d91SShunqian Zheng static const int ov2685_test_pattern_val[] = { 225e3861d91SShunqian Zheng OV2685_TEST_PATTERN_DISABLED, 226e3861d91SShunqian Zheng OV2685_TEST_PATTERN_COLOR_BAR, 227e3861d91SShunqian Zheng OV2685_TEST_PATTERN_COLOR_BAR_FADE, 228e3861d91SShunqian Zheng OV2685_TEST_PATTERN_RANDOM, 229e3861d91SShunqian Zheng OV2685_TEST_PATTERN_BW_SQUARE, 230e3861d91SShunqian Zheng OV2685_TEST_PATTERN_COLOR_SQUARE, 231e3861d91SShunqian Zheng }; 232e3861d91SShunqian Zheng 233e3861d91SShunqian Zheng static const struct ov2685_mode supported_modes[] = { 234e3861d91SShunqian Zheng { 235e3861d91SShunqian Zheng .width = 1600, 236e3861d91SShunqian Zheng .height = 1200, 237e3861d91SShunqian Zheng .exp_def = 0x04ee, 238e3861d91SShunqian Zheng .hts_def = 0x06a4, 239e3861d91SShunqian Zheng .vts_def = 0x050e, 240e3861d91SShunqian Zheng .reg_list = ov2685_1600x1200_regs, 241e3861d91SShunqian Zheng }, 242e3861d91SShunqian Zheng }; 243e3861d91SShunqian Zheng 244e3861d91SShunqian Zheng /* Write registers up to 4 at a time */ 245e3861d91SShunqian Zheng static int ov2685_write_reg(struct i2c_client *client, u16 reg, 246e3861d91SShunqian Zheng u32 len, u32 val) 247e3861d91SShunqian Zheng { 248e3861d91SShunqian Zheng u32 val_i, buf_i; 249e3861d91SShunqian Zheng u8 buf[6]; 250e3861d91SShunqian Zheng u8 *val_p; 251e3861d91SShunqian Zheng __be32 val_be; 252e3861d91SShunqian Zheng 253e3861d91SShunqian Zheng if (len > 4) 254e3861d91SShunqian Zheng return -EINVAL; 255e3861d91SShunqian Zheng 256e3861d91SShunqian Zheng buf[0] = reg >> 8; 257e3861d91SShunqian Zheng buf[1] = reg & 0xff; 258e3861d91SShunqian Zheng 259e3861d91SShunqian Zheng val_be = cpu_to_be32(val); 260e3861d91SShunqian Zheng val_p = (u8 *)&val_be; 261e3861d91SShunqian Zheng buf_i = 2; 262e3861d91SShunqian Zheng val_i = 4 - len; 263e3861d91SShunqian Zheng 264e3861d91SShunqian Zheng while (val_i < 4) 265e3861d91SShunqian Zheng buf[buf_i++] = val_p[val_i++]; 266e3861d91SShunqian Zheng 267e3861d91SShunqian Zheng if (i2c_master_send(client, buf, len + 2) != len + 2) 268e3861d91SShunqian Zheng return -EIO; 269e3861d91SShunqian Zheng 270e3861d91SShunqian Zheng return 0; 271e3861d91SShunqian Zheng } 272e3861d91SShunqian Zheng 273e3861d91SShunqian Zheng static int ov2685_write_array(struct i2c_client *client, 274e3861d91SShunqian Zheng const struct regval *regs) 275e3861d91SShunqian Zheng { 276e3861d91SShunqian Zheng int ret = 0; 277e3861d91SShunqian Zheng u32 i; 278e3861d91SShunqian Zheng 279e3861d91SShunqian Zheng for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) 280e3861d91SShunqian Zheng ret = ov2685_write_reg(client, regs[i].addr, 281e3861d91SShunqian Zheng OV2685_REG_VALUE_08BIT, regs[i].val); 282e3861d91SShunqian Zheng 283e3861d91SShunqian Zheng return ret; 284e3861d91SShunqian Zheng } 285e3861d91SShunqian Zheng 286e3861d91SShunqian Zheng /* Read registers up to 4 at a time */ 287e3861d91SShunqian Zheng static int ov2685_read_reg(struct i2c_client *client, u16 reg, 288e3861d91SShunqian Zheng u32 len, u32 *val) 289e3861d91SShunqian Zheng { 290e3861d91SShunqian Zheng struct i2c_msg msgs[2]; 291e3861d91SShunqian Zheng u8 *data_be_p; 292e3861d91SShunqian Zheng __be32 data_be = 0; 293e3861d91SShunqian Zheng __be16 reg_addr_be = cpu_to_be16(reg); 294e3861d91SShunqian Zheng int ret; 295e3861d91SShunqian Zheng 296e3861d91SShunqian Zheng if (len > 4) 297e3861d91SShunqian Zheng return -EINVAL; 298e3861d91SShunqian Zheng 299e3861d91SShunqian Zheng data_be_p = (u8 *)&data_be; 300e3861d91SShunqian Zheng /* Write register address */ 301e3861d91SShunqian Zheng msgs[0].addr = client->addr; 302e3861d91SShunqian Zheng msgs[0].flags = 0; 303e3861d91SShunqian Zheng msgs[0].len = 2; 304e3861d91SShunqian Zheng msgs[0].buf = (u8 *)®_addr_be; 305e3861d91SShunqian Zheng 306e3861d91SShunqian Zheng /* Read data from register */ 307e3861d91SShunqian Zheng msgs[1].addr = client->addr; 308e3861d91SShunqian Zheng msgs[1].flags = I2C_M_RD; 309e3861d91SShunqian Zheng msgs[1].len = len; 310e3861d91SShunqian Zheng msgs[1].buf = &data_be_p[4 - len]; 311e3861d91SShunqian Zheng 312e3861d91SShunqian Zheng ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 313e3861d91SShunqian Zheng if (ret != ARRAY_SIZE(msgs)) 314e3861d91SShunqian Zheng return -EIO; 315e3861d91SShunqian Zheng 316e3861d91SShunqian Zheng *val = be32_to_cpu(data_be); 317e3861d91SShunqian Zheng 318e3861d91SShunqian Zheng return 0; 319e3861d91SShunqian Zheng } 320e3861d91SShunqian Zheng 321e3861d91SShunqian Zheng static void ov2685_fill_fmt(const struct ov2685_mode *mode, 322e3861d91SShunqian Zheng struct v4l2_mbus_framefmt *fmt) 323e3861d91SShunqian Zheng { 324e3861d91SShunqian Zheng fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; 325e3861d91SShunqian Zheng fmt->width = mode->width; 326e3861d91SShunqian Zheng fmt->height = mode->height; 327e3861d91SShunqian Zheng fmt->field = V4L2_FIELD_NONE; 328e3861d91SShunqian Zheng } 329e3861d91SShunqian Zheng 330e3861d91SShunqian Zheng static int ov2685_set_fmt(struct v4l2_subdev *sd, 331e3861d91SShunqian Zheng struct v4l2_subdev_pad_config *cfg, 332e3861d91SShunqian Zheng struct v4l2_subdev_format *fmt) 333e3861d91SShunqian Zheng { 334e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 335e3861d91SShunqian Zheng struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; 336e3861d91SShunqian Zheng 337e3861d91SShunqian Zheng /* only one mode supported for now */ 338e3861d91SShunqian Zheng ov2685_fill_fmt(ov2685->cur_mode, mbus_fmt); 339e3861d91SShunqian Zheng 340e3861d91SShunqian Zheng return 0; 341e3861d91SShunqian Zheng } 342e3861d91SShunqian Zheng 343e3861d91SShunqian Zheng static int ov2685_get_fmt(struct v4l2_subdev *sd, 344e3861d91SShunqian Zheng struct v4l2_subdev_pad_config *cfg, 345e3861d91SShunqian Zheng struct v4l2_subdev_format *fmt) 346e3861d91SShunqian Zheng { 347e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 348e3861d91SShunqian Zheng struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; 349e3861d91SShunqian Zheng 350e3861d91SShunqian Zheng ov2685_fill_fmt(ov2685->cur_mode, mbus_fmt); 351e3861d91SShunqian Zheng 352e3861d91SShunqian Zheng return 0; 353e3861d91SShunqian Zheng } 354e3861d91SShunqian Zheng 355e3861d91SShunqian Zheng static int ov2685_enum_mbus_code(struct v4l2_subdev *sd, 356e3861d91SShunqian Zheng struct v4l2_subdev_pad_config *cfg, 357e3861d91SShunqian Zheng struct v4l2_subdev_mbus_code_enum *code) 358e3861d91SShunqian Zheng { 359e3861d91SShunqian Zheng if (code->index >= ARRAY_SIZE(supported_modes)) 360e3861d91SShunqian Zheng return -EINVAL; 361e3861d91SShunqian Zheng 362e3861d91SShunqian Zheng code->code = MEDIA_BUS_FMT_SBGGR10_1X10; 363e3861d91SShunqian Zheng 364e3861d91SShunqian Zheng return 0; 365e3861d91SShunqian Zheng } 366e3861d91SShunqian Zheng 367e3861d91SShunqian Zheng static int ov2685_enum_frame_sizes(struct v4l2_subdev *sd, 368e3861d91SShunqian Zheng struct v4l2_subdev_pad_config *cfg, 369e3861d91SShunqian Zheng struct v4l2_subdev_frame_size_enum *fse) 370e3861d91SShunqian Zheng { 371e3861d91SShunqian Zheng int index = fse->index; 372e3861d91SShunqian Zheng 373e3861d91SShunqian Zheng if (index >= ARRAY_SIZE(supported_modes)) 374e3861d91SShunqian Zheng return -EINVAL; 375e3861d91SShunqian Zheng 376e3861d91SShunqian Zheng fse->code = MEDIA_BUS_FMT_SBGGR10_1X10; 377e3861d91SShunqian Zheng 378e3861d91SShunqian Zheng fse->min_width = supported_modes[index].width; 379e3861d91SShunqian Zheng fse->max_width = supported_modes[index].width; 380e3861d91SShunqian Zheng fse->max_height = supported_modes[index].height; 381e3861d91SShunqian Zheng fse->min_height = supported_modes[index].height; 382e3861d91SShunqian Zheng 383e3861d91SShunqian Zheng return 0; 384e3861d91SShunqian Zheng } 385e3861d91SShunqian Zheng 386e3861d91SShunqian Zheng /* Calculate the delay in us by clock rate and clock cycles */ 387e3861d91SShunqian Zheng static inline u32 ov2685_cal_delay(u32 cycles) 388e3861d91SShunqian Zheng { 389e3861d91SShunqian Zheng return DIV_ROUND_UP(cycles, OV2685_XVCLK_FREQ / 1000 / 1000); 390e3861d91SShunqian Zheng } 391e3861d91SShunqian Zheng 392e3861d91SShunqian Zheng static int __ov2685_power_on(struct ov2685 *ov2685) 393e3861d91SShunqian Zheng { 394e3861d91SShunqian Zheng int ret; 395e3861d91SShunqian Zheng u32 delay_us; 396e3861d91SShunqian Zheng struct device *dev = &ov2685->client->dev; 397e3861d91SShunqian Zheng 398e3861d91SShunqian Zheng ret = clk_prepare_enable(ov2685->xvclk); 399e3861d91SShunqian Zheng if (ret < 0) { 400e3861d91SShunqian Zheng dev_err(dev, "Failed to enable xvclk\n"); 401e3861d91SShunqian Zheng return ret; 402e3861d91SShunqian Zheng } 403e3861d91SShunqian Zheng 404e3861d91SShunqian Zheng gpiod_set_value_cansleep(ov2685->reset_gpio, 1); 405e3861d91SShunqian Zheng 406e3861d91SShunqian Zheng ret = regulator_bulk_enable(OV2685_NUM_SUPPLIES, ov2685->supplies); 407e3861d91SShunqian Zheng if (ret < 0) { 408e3861d91SShunqian Zheng dev_err(dev, "Failed to enable regulators\n"); 409e3861d91SShunqian Zheng goto disable_clk; 410e3861d91SShunqian Zheng } 411e3861d91SShunqian Zheng 412e3861d91SShunqian Zheng /* The minimum delay between power supplies and reset rising can be 0 */ 413e3861d91SShunqian Zheng gpiod_set_value_cansleep(ov2685->reset_gpio, 0); 414e3861d91SShunqian Zheng /* 8192 xvclk cycles prior to the first SCCB transaction */ 415e3861d91SShunqian Zheng delay_us = ov2685_cal_delay(8192); 416e3861d91SShunqian Zheng usleep_range(delay_us, delay_us * 2); 417e3861d91SShunqian Zheng 418e3861d91SShunqian Zheng /* HACK: ov2685 would output messy data after reset(R0103), 419e3861d91SShunqian Zheng * writing register before .s_stream() as a workaround 420e3861d91SShunqian Zheng */ 421e3861d91SShunqian Zheng ret = ov2685_write_array(ov2685->client, ov2685->cur_mode->reg_list); 422e3861d91SShunqian Zheng if (ret) 423e3861d91SShunqian Zheng goto disable_supplies; 424e3861d91SShunqian Zheng 425e3861d91SShunqian Zheng return 0; 426e3861d91SShunqian Zheng 427e3861d91SShunqian Zheng disable_supplies: 428e3861d91SShunqian Zheng regulator_bulk_disable(OV2685_NUM_SUPPLIES, ov2685->supplies); 429e3861d91SShunqian Zheng disable_clk: 430e3861d91SShunqian Zheng clk_disable_unprepare(ov2685->xvclk); 431e3861d91SShunqian Zheng 432e3861d91SShunqian Zheng return ret; 433e3861d91SShunqian Zheng } 434e3861d91SShunqian Zheng 435e3861d91SShunqian Zheng static void __ov2685_power_off(struct ov2685 *ov2685) 436e3861d91SShunqian Zheng { 437e3861d91SShunqian Zheng /* 512 xvclk cycles after the last SCCB transaction or MIPI frame end */ 438e3861d91SShunqian Zheng u32 delay_us = ov2685_cal_delay(512); 439e3861d91SShunqian Zheng 440e3861d91SShunqian Zheng usleep_range(delay_us, delay_us * 2); 441e3861d91SShunqian Zheng clk_disable_unprepare(ov2685->xvclk); 442e3861d91SShunqian Zheng gpiod_set_value_cansleep(ov2685->reset_gpio, 1); 443e3861d91SShunqian Zheng regulator_bulk_disable(OV2685_NUM_SUPPLIES, ov2685->supplies); 444e3861d91SShunqian Zheng } 445e3861d91SShunqian Zheng 446e3861d91SShunqian Zheng static int ov2685_s_stream(struct v4l2_subdev *sd, int on) 447e3861d91SShunqian Zheng { 448e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 449e3861d91SShunqian Zheng struct i2c_client *client = ov2685->client; 450e3861d91SShunqian Zheng int ret = 0; 451e3861d91SShunqian Zheng 452e3861d91SShunqian Zheng mutex_lock(&ov2685->mutex); 453e3861d91SShunqian Zheng 454e3861d91SShunqian Zheng on = !!on; 455e3861d91SShunqian Zheng if (on == ov2685->streaming) 456e3861d91SShunqian Zheng goto unlock_and_return; 457e3861d91SShunqian Zheng 458e3861d91SShunqian Zheng if (on) { 459e3861d91SShunqian Zheng ret = pm_runtime_get_sync(&ov2685->client->dev); 460e3861d91SShunqian Zheng if (ret < 0) { 461e3861d91SShunqian Zheng pm_runtime_put_noidle(&client->dev); 462e3861d91SShunqian Zheng goto unlock_and_return; 463e3861d91SShunqian Zheng } 464e3861d91SShunqian Zheng ret = __v4l2_ctrl_handler_setup(&ov2685->ctrl_handler); 465e3861d91SShunqian Zheng if (ret) { 466e3861d91SShunqian Zheng pm_runtime_put(&client->dev); 467e3861d91SShunqian Zheng goto unlock_and_return; 468e3861d91SShunqian Zheng } 469e3861d91SShunqian Zheng ret = ov2685_write_reg(client, REG_SC_CTRL_MODE, 470e3861d91SShunqian Zheng OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STREAMING); 471e3861d91SShunqian Zheng if (ret) { 472e3861d91SShunqian Zheng pm_runtime_put(&client->dev); 473e3861d91SShunqian Zheng goto unlock_and_return; 474e3861d91SShunqian Zheng } 475e3861d91SShunqian Zheng } else { 476e3861d91SShunqian Zheng ov2685_write_reg(client, REG_SC_CTRL_MODE, 477e3861d91SShunqian Zheng OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STANDBY); 478e3861d91SShunqian Zheng pm_runtime_put(&ov2685->client->dev); 479e3861d91SShunqian Zheng } 480e3861d91SShunqian Zheng 481e3861d91SShunqian Zheng ov2685->streaming = on; 482e3861d91SShunqian Zheng 483e3861d91SShunqian Zheng unlock_and_return: 484e3861d91SShunqian Zheng mutex_unlock(&ov2685->mutex); 485e3861d91SShunqian Zheng 486e3861d91SShunqian Zheng return ret; 487e3861d91SShunqian Zheng } 488e3861d91SShunqian Zheng 489e3861d91SShunqian Zheng #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 490e3861d91SShunqian Zheng static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 491e3861d91SShunqian Zheng { 492e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 493e3861d91SShunqian Zheng struct v4l2_mbus_framefmt *try_fmt; 494e3861d91SShunqian Zheng 495e3861d91SShunqian Zheng mutex_lock(&ov2685->mutex); 496e3861d91SShunqian Zheng 497e3861d91SShunqian Zheng try_fmt = v4l2_subdev_get_try_format(sd, fh->pad, 0); 498e3861d91SShunqian Zheng /* Initialize try_fmt */ 499e3861d91SShunqian Zheng ov2685_fill_fmt(&supported_modes[0], try_fmt); 500e3861d91SShunqian Zheng 501e3861d91SShunqian Zheng mutex_unlock(&ov2685->mutex); 502e3861d91SShunqian Zheng 503e3861d91SShunqian Zheng return 0; 504e3861d91SShunqian Zheng } 505e3861d91SShunqian Zheng #endif 506e3861d91SShunqian Zheng 507e3861d91SShunqian Zheng static int ov2685_runtime_resume(struct device *dev) 508e3861d91SShunqian Zheng { 509e3861d91SShunqian Zheng struct i2c_client *client = to_i2c_client(dev); 510e3861d91SShunqian Zheng struct v4l2_subdev *sd = i2c_get_clientdata(client); 511e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 512e3861d91SShunqian Zheng 513e3861d91SShunqian Zheng return __ov2685_power_on(ov2685); 514e3861d91SShunqian Zheng } 515e3861d91SShunqian Zheng 516e3861d91SShunqian Zheng static int ov2685_runtime_suspend(struct device *dev) 517e3861d91SShunqian Zheng { 518e3861d91SShunqian Zheng struct i2c_client *client = to_i2c_client(dev); 519e3861d91SShunqian Zheng struct v4l2_subdev *sd = i2c_get_clientdata(client); 520e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 521e3861d91SShunqian Zheng 522e3861d91SShunqian Zheng __ov2685_power_off(ov2685); 523e3861d91SShunqian Zheng 524e3861d91SShunqian Zheng return 0; 525e3861d91SShunqian Zheng } 526e3861d91SShunqian Zheng 527e3861d91SShunqian Zheng static const struct dev_pm_ops ov2685_pm_ops = { 528e3861d91SShunqian Zheng SET_RUNTIME_PM_OPS(ov2685_runtime_suspend, 529e3861d91SShunqian Zheng ov2685_runtime_resume, NULL) 530e3861d91SShunqian Zheng }; 531e3861d91SShunqian Zheng 532e3861d91SShunqian Zheng static int ov2685_set_ctrl(struct v4l2_ctrl *ctrl) 533e3861d91SShunqian Zheng { 534e3861d91SShunqian Zheng struct ov2685 *ov2685 = container_of(ctrl->handler, 535e3861d91SShunqian Zheng struct ov2685, ctrl_handler); 536e3861d91SShunqian Zheng struct i2c_client *client = ov2685->client; 537e3861d91SShunqian Zheng s64 max_expo; 538e3861d91SShunqian Zheng int ret; 539e3861d91SShunqian Zheng 540e3861d91SShunqian Zheng /* Propagate change of current control to all related controls */ 541e3861d91SShunqian Zheng switch (ctrl->id) { 542e3861d91SShunqian Zheng case V4L2_CID_VBLANK: 543e3861d91SShunqian Zheng /* Update max exposure while meeting expected vblanking */ 544e3861d91SShunqian Zheng max_expo = ov2685->cur_mode->height + ctrl->val - 4; 545e3861d91SShunqian Zheng __v4l2_ctrl_modify_range(ov2685->exposure, 546e3861d91SShunqian Zheng ov2685->exposure->minimum, max_expo, 547e3861d91SShunqian Zheng ov2685->exposure->step, 548e3861d91SShunqian Zheng ov2685->exposure->default_value); 549e3861d91SShunqian Zheng break; 550e3861d91SShunqian Zheng } 551e3861d91SShunqian Zheng 552e3861d91SShunqian Zheng if (pm_runtime_get_if_in_use(&client->dev) <= 0) 553e3861d91SShunqian Zheng return 0; 554e3861d91SShunqian Zheng 555e3861d91SShunqian Zheng switch (ctrl->id) { 556e3861d91SShunqian Zheng case V4L2_CID_EXPOSURE: 557e3861d91SShunqian Zheng ret = ov2685_write_reg(ov2685->client, OV2685_REG_EXPOSURE, 558e3861d91SShunqian Zheng OV2685_REG_VALUE_24BIT, ctrl->val << 4); 559e3861d91SShunqian Zheng break; 560e3861d91SShunqian Zheng case V4L2_CID_ANALOGUE_GAIN: 561e3861d91SShunqian Zheng ret = ov2685_write_reg(ov2685->client, OV2685_REG_GAIN, 562e3861d91SShunqian Zheng OV2685_REG_VALUE_16BIT, ctrl->val); 563e3861d91SShunqian Zheng break; 564e3861d91SShunqian Zheng case V4L2_CID_VBLANK: 565e3861d91SShunqian Zheng ret = ov2685_write_reg(ov2685->client, OV2685_REG_VTS, 566e3861d91SShunqian Zheng OV2685_REG_VALUE_16BIT, 567e3861d91SShunqian Zheng ctrl->val + ov2685->cur_mode->height); 568e3861d91SShunqian Zheng break; 569e3861d91SShunqian Zheng case V4L2_CID_TEST_PATTERN: 570e3861d91SShunqian Zheng ret = ov2685_write_reg(ov2685->client, OV2685_REG_TEST_PATTERN, 571e3861d91SShunqian Zheng OV2685_REG_VALUE_08BIT, 572e3861d91SShunqian Zheng ov2685_test_pattern_val[ctrl->val]); 573e3861d91SShunqian Zheng break; 574e3861d91SShunqian Zheng default: 575e3861d91SShunqian Zheng dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", 576e3861d91SShunqian Zheng __func__, ctrl->id, ctrl->val); 577e3861d91SShunqian Zheng break; 578e3861d91SShunqian Zheng }; 579e3861d91SShunqian Zheng 580e3861d91SShunqian Zheng pm_runtime_put(&client->dev); 581e3861d91SShunqian Zheng 582e3861d91SShunqian Zheng return ret; 583e3861d91SShunqian Zheng } 584e3861d91SShunqian Zheng 585e3861d91SShunqian Zheng static const struct v4l2_subdev_video_ops ov2685_video_ops = { 586e3861d91SShunqian Zheng .s_stream = ov2685_s_stream, 587e3861d91SShunqian Zheng }; 588e3861d91SShunqian Zheng 589e3861d91SShunqian Zheng static const struct v4l2_subdev_pad_ops ov2685_pad_ops = { 590e3861d91SShunqian Zheng .enum_mbus_code = ov2685_enum_mbus_code, 591e3861d91SShunqian Zheng .enum_frame_size = ov2685_enum_frame_sizes, 592e3861d91SShunqian Zheng .get_fmt = ov2685_get_fmt, 593e3861d91SShunqian Zheng .set_fmt = ov2685_set_fmt, 594e3861d91SShunqian Zheng }; 595e3861d91SShunqian Zheng 596e3861d91SShunqian Zheng static const struct v4l2_subdev_ops ov2685_subdev_ops = { 597e3861d91SShunqian Zheng .video = &ov2685_video_ops, 598e3861d91SShunqian Zheng .pad = &ov2685_pad_ops, 599e3861d91SShunqian Zheng }; 600e3861d91SShunqian Zheng 601e3861d91SShunqian Zheng #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 602e3861d91SShunqian Zheng static const struct v4l2_subdev_internal_ops ov2685_internal_ops = { 603e3861d91SShunqian Zheng .open = ov2685_open, 604e3861d91SShunqian Zheng }; 605e3861d91SShunqian Zheng #endif 606e3861d91SShunqian Zheng 607e3861d91SShunqian Zheng static const struct v4l2_ctrl_ops ov2685_ctrl_ops = { 608e3861d91SShunqian Zheng .s_ctrl = ov2685_set_ctrl, 609e3861d91SShunqian Zheng }; 610e3861d91SShunqian Zheng 611e3861d91SShunqian Zheng static int ov2685_initialize_controls(struct ov2685 *ov2685) 612e3861d91SShunqian Zheng { 613e3861d91SShunqian Zheng const struct ov2685_mode *mode; 614e3861d91SShunqian Zheng struct v4l2_ctrl_handler *handler; 615e3861d91SShunqian Zheng struct v4l2_ctrl *ctrl; 616e3861d91SShunqian Zheng u64 exposure_max; 617e3861d91SShunqian Zheng u32 pixel_rate, h_blank; 618e3861d91SShunqian Zheng int ret; 619e3861d91SShunqian Zheng 620e3861d91SShunqian Zheng handler = &ov2685->ctrl_handler; 621e3861d91SShunqian Zheng mode = ov2685->cur_mode; 622e3861d91SShunqian Zheng ret = v4l2_ctrl_handler_init(handler, 8); 623e3861d91SShunqian Zheng if (ret) 624e3861d91SShunqian Zheng return ret; 625e3861d91SShunqian Zheng handler->lock = &ov2685->mutex; 626e3861d91SShunqian Zheng 627e3861d91SShunqian Zheng ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, 628e3861d91SShunqian Zheng 0, 0, link_freq_menu_items); 629e3861d91SShunqian Zheng if (ctrl) 630e3861d91SShunqian Zheng ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 631e3861d91SShunqian Zheng 632e3861d91SShunqian Zheng pixel_rate = (link_freq_menu_items[0] * 2 * OV2685_LANES) / 633e3861d91SShunqian Zheng OV2685_BITS_PER_SAMPLE; 634e3861d91SShunqian Zheng v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 635e3861d91SShunqian Zheng 0, pixel_rate, 1, pixel_rate); 636e3861d91SShunqian Zheng 637e3861d91SShunqian Zheng h_blank = mode->hts_def - mode->width; 638e3861d91SShunqian Zheng ov2685->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, 639e3861d91SShunqian Zheng h_blank, h_blank, 1, h_blank); 640e3861d91SShunqian Zheng if (ov2685->hblank) 641e3861d91SShunqian Zheng ov2685->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; 642e3861d91SShunqian Zheng 643e3861d91SShunqian Zheng ov2685->vblank = v4l2_ctrl_new_std(handler, &ov2685_ctrl_ops, 644e3861d91SShunqian Zheng V4L2_CID_VBLANK, mode->vts_def - mode->height, 645e3861d91SShunqian Zheng OV2685_VTS_MAX - mode->height, 1, 646e3861d91SShunqian Zheng mode->vts_def - mode->height); 647e3861d91SShunqian Zheng 648e3861d91SShunqian Zheng exposure_max = mode->vts_def - 4; 649e3861d91SShunqian Zheng ov2685->exposure = v4l2_ctrl_new_std(handler, &ov2685_ctrl_ops, 650e3861d91SShunqian Zheng V4L2_CID_EXPOSURE, OV2685_EXPOSURE_MIN, 651e3861d91SShunqian Zheng exposure_max, OV2685_EXPOSURE_STEP, 652e3861d91SShunqian Zheng mode->exp_def); 653e3861d91SShunqian Zheng 654e3861d91SShunqian Zheng ov2685->anal_gain = v4l2_ctrl_new_std(handler, &ov2685_ctrl_ops, 655e3861d91SShunqian Zheng V4L2_CID_ANALOGUE_GAIN, OV2685_GAIN_MIN, 656e3861d91SShunqian Zheng OV2685_GAIN_MAX, OV2685_GAIN_STEP, 657e3861d91SShunqian Zheng OV2685_GAIN_DEFAULT); 658e3861d91SShunqian Zheng 659e3861d91SShunqian Zheng ov2685->test_pattern = v4l2_ctrl_new_std_menu_items(handler, 660e3861d91SShunqian Zheng &ov2685_ctrl_ops, V4L2_CID_TEST_PATTERN, 661e3861d91SShunqian Zheng ARRAY_SIZE(ov2685_test_pattern_menu) - 1, 662e3861d91SShunqian Zheng 0, 0, ov2685_test_pattern_menu); 663e3861d91SShunqian Zheng 664e3861d91SShunqian Zheng if (handler->error) { 665e3861d91SShunqian Zheng ret = handler->error; 666e3861d91SShunqian Zheng dev_err(&ov2685->client->dev, 667e3861d91SShunqian Zheng "Failed to init controls(%d)\n", ret); 668e3861d91SShunqian Zheng goto err_free_handler; 669e3861d91SShunqian Zheng } 670e3861d91SShunqian Zheng 671e3861d91SShunqian Zheng ov2685->subdev.ctrl_handler = handler; 672e3861d91SShunqian Zheng 673e3861d91SShunqian Zheng return 0; 674e3861d91SShunqian Zheng 675e3861d91SShunqian Zheng err_free_handler: 676e3861d91SShunqian Zheng v4l2_ctrl_handler_free(handler); 677e3861d91SShunqian Zheng 678e3861d91SShunqian Zheng return ret; 679e3861d91SShunqian Zheng } 680e3861d91SShunqian Zheng 681e3861d91SShunqian Zheng static int ov2685_check_sensor_id(struct ov2685 *ov2685, 682e3861d91SShunqian Zheng struct i2c_client *client) 683e3861d91SShunqian Zheng { 684e3861d91SShunqian Zheng struct device *dev = &ov2685->client->dev; 685e3861d91SShunqian Zheng int ret; 686e3861d91SShunqian Zheng u32 id = 0; 687e3861d91SShunqian Zheng 688e3861d91SShunqian Zheng ret = ov2685_read_reg(client, OV2685_REG_CHIP_ID, 689e3861d91SShunqian Zheng OV2685_REG_VALUE_16BIT, &id); 690e3861d91SShunqian Zheng if (id != CHIP_ID) { 691e3861d91SShunqian Zheng dev_err(dev, "Unexpected sensor id(%04x), ret(%d)\n", id, ret); 692e3861d91SShunqian Zheng return ret; 693e3861d91SShunqian Zheng } 694e3861d91SShunqian Zheng 695e3861d91SShunqian Zheng dev_info(dev, "Detected OV%04x sensor\n", CHIP_ID); 696e3861d91SShunqian Zheng 697e3861d91SShunqian Zheng return 0; 698e3861d91SShunqian Zheng } 699e3861d91SShunqian Zheng 700e3861d91SShunqian Zheng static int ov2685_configure_regulators(struct ov2685 *ov2685) 701e3861d91SShunqian Zheng { 702e3861d91SShunqian Zheng int i; 703e3861d91SShunqian Zheng 704e3861d91SShunqian Zheng for (i = 0; i < OV2685_NUM_SUPPLIES; i++) 705e3861d91SShunqian Zheng ov2685->supplies[i].supply = ov2685_supply_names[i]; 706e3861d91SShunqian Zheng 707e3861d91SShunqian Zheng return devm_regulator_bulk_get(&ov2685->client->dev, 708e3861d91SShunqian Zheng OV2685_NUM_SUPPLIES, 709e3861d91SShunqian Zheng ov2685->supplies); 710e3861d91SShunqian Zheng } 711e3861d91SShunqian Zheng 712e3861d91SShunqian Zheng static int ov2685_probe(struct i2c_client *client, 713e3861d91SShunqian Zheng const struct i2c_device_id *id) 714e3861d91SShunqian Zheng { 715e3861d91SShunqian Zheng struct device *dev = &client->dev; 716e3861d91SShunqian Zheng struct ov2685 *ov2685; 717e3861d91SShunqian Zheng int ret; 718e3861d91SShunqian Zheng 719e3861d91SShunqian Zheng ov2685 = devm_kzalloc(dev, sizeof(*ov2685), GFP_KERNEL); 720e3861d91SShunqian Zheng if (!ov2685) 721e3861d91SShunqian Zheng return -ENOMEM; 722e3861d91SShunqian Zheng 723e3861d91SShunqian Zheng ov2685->client = client; 724e3861d91SShunqian Zheng ov2685->cur_mode = &supported_modes[0]; 725e3861d91SShunqian Zheng 726e3861d91SShunqian Zheng ov2685->xvclk = devm_clk_get(dev, "xvclk"); 727e3861d91SShunqian Zheng if (IS_ERR(ov2685->xvclk)) { 728e3861d91SShunqian Zheng dev_err(dev, "Failed to get xvclk\n"); 729e3861d91SShunqian Zheng return -EINVAL; 730e3861d91SShunqian Zheng } 731e3861d91SShunqian Zheng ret = clk_set_rate(ov2685->xvclk, OV2685_XVCLK_FREQ); 732e3861d91SShunqian Zheng if (ret < 0) { 733e3861d91SShunqian Zheng dev_err(dev, "Failed to set xvclk rate (24MHz)\n"); 734e3861d91SShunqian Zheng return ret; 735e3861d91SShunqian Zheng } 736e3861d91SShunqian Zheng if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ) 737e3861d91SShunqian Zheng dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); 738e3861d91SShunqian Zheng 739e3861d91SShunqian Zheng ov2685->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 740e3861d91SShunqian Zheng if (IS_ERR(ov2685->reset_gpio)) { 741e3861d91SShunqian Zheng dev_err(dev, "Failed to get reset-gpios\n"); 742e3861d91SShunqian Zheng return -EINVAL; 743e3861d91SShunqian Zheng } 744e3861d91SShunqian Zheng 745e3861d91SShunqian Zheng ret = ov2685_configure_regulators(ov2685); 746e3861d91SShunqian Zheng if (ret) { 747e3861d91SShunqian Zheng dev_err(dev, "Failed to get power regulators\n"); 748e3861d91SShunqian Zheng return ret; 749e3861d91SShunqian Zheng } 750e3861d91SShunqian Zheng 751e3861d91SShunqian Zheng mutex_init(&ov2685->mutex); 752e3861d91SShunqian Zheng v4l2_i2c_subdev_init(&ov2685->subdev, client, &ov2685_subdev_ops); 753e3861d91SShunqian Zheng ret = ov2685_initialize_controls(ov2685); 754e3861d91SShunqian Zheng if (ret) 755e3861d91SShunqian Zheng goto err_destroy_mutex; 756e3861d91SShunqian Zheng 757e3861d91SShunqian Zheng ret = __ov2685_power_on(ov2685); 758e3861d91SShunqian Zheng if (ret) 759e3861d91SShunqian Zheng goto err_free_handler; 760e3861d91SShunqian Zheng 761e3861d91SShunqian Zheng ret = ov2685_check_sensor_id(ov2685, client); 762e3861d91SShunqian Zheng if (ret) 763e3861d91SShunqian Zheng goto err_power_off; 764e3861d91SShunqian Zheng 765e3861d91SShunqian Zheng #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 766e3861d91SShunqian Zheng ov2685->subdev.internal_ops = &ov2685_internal_ops; 767e3861d91SShunqian Zheng ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 768e3861d91SShunqian Zheng #endif 769e3861d91SShunqian Zheng #if defined(CONFIG_MEDIA_CONTROLLER) 770e3861d91SShunqian Zheng ov2685->pad.flags = MEDIA_PAD_FL_SOURCE; 771e3861d91SShunqian Zheng ov2685->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; 772e3861d91SShunqian Zheng ret = media_entity_pads_init(&ov2685->subdev.entity, 1, &ov2685->pad); 773e3861d91SShunqian Zheng if (ret < 0) 774e3861d91SShunqian Zheng goto err_power_off; 775e3861d91SShunqian Zheng #endif 776e3861d91SShunqian Zheng 777e3861d91SShunqian Zheng ret = v4l2_async_register_subdev(&ov2685->subdev); 778e3861d91SShunqian Zheng if (ret) { 779e3861d91SShunqian Zheng dev_err(dev, "v4l2 async register subdev failed\n"); 780e3861d91SShunqian Zheng goto err_clean_entity; 781e3861d91SShunqian Zheng } 782e3861d91SShunqian Zheng 783e3861d91SShunqian Zheng pm_runtime_set_active(dev); 784e3861d91SShunqian Zheng pm_runtime_enable(dev); 785e3861d91SShunqian Zheng pm_runtime_idle(dev); 786e3861d91SShunqian Zheng 787e3861d91SShunqian Zheng return 0; 788e3861d91SShunqian Zheng 789e3861d91SShunqian Zheng err_clean_entity: 790e3861d91SShunqian Zheng #if defined(CONFIG_MEDIA_CONTROLLER) 791e3861d91SShunqian Zheng media_entity_cleanup(&ov2685->subdev.entity); 792e3861d91SShunqian Zheng #endif 793e3861d91SShunqian Zheng err_power_off: 794e3861d91SShunqian Zheng __ov2685_power_off(ov2685); 795e3861d91SShunqian Zheng err_free_handler: 796e3861d91SShunqian Zheng v4l2_ctrl_handler_free(&ov2685->ctrl_handler); 797e3861d91SShunqian Zheng err_destroy_mutex: 798e3861d91SShunqian Zheng mutex_destroy(&ov2685->mutex); 799e3861d91SShunqian Zheng 800e3861d91SShunqian Zheng return ret; 801e3861d91SShunqian Zheng } 802e3861d91SShunqian Zheng 803e3861d91SShunqian Zheng static int ov2685_remove(struct i2c_client *client) 804e3861d91SShunqian Zheng { 805e3861d91SShunqian Zheng struct v4l2_subdev *sd = i2c_get_clientdata(client); 806e3861d91SShunqian Zheng struct ov2685 *ov2685 = to_ov2685(sd); 807e3861d91SShunqian Zheng 808e3861d91SShunqian Zheng v4l2_async_unregister_subdev(sd); 809e3861d91SShunqian Zheng #if defined(CONFIG_MEDIA_CONTROLLER) 810e3861d91SShunqian Zheng media_entity_cleanup(&sd->entity); 811e3861d91SShunqian Zheng #endif 812e3861d91SShunqian Zheng v4l2_ctrl_handler_free(&ov2685->ctrl_handler); 813e3861d91SShunqian Zheng mutex_destroy(&ov2685->mutex); 814e3861d91SShunqian Zheng 815e3861d91SShunqian Zheng pm_runtime_disable(&client->dev); 816e3861d91SShunqian Zheng if (!pm_runtime_status_suspended(&client->dev)) 817e3861d91SShunqian Zheng __ov2685_power_off(ov2685); 818e3861d91SShunqian Zheng pm_runtime_set_suspended(&client->dev); 819e3861d91SShunqian Zheng 820e3861d91SShunqian Zheng return 0; 821e3861d91SShunqian Zheng } 822e3861d91SShunqian Zheng 823e3861d91SShunqian Zheng #if IS_ENABLED(CONFIG_OF) 824e3861d91SShunqian Zheng static const struct of_device_id ov2685_of_match[] = { 825e3861d91SShunqian Zheng { .compatible = "ovti,ov2685" }, 826e3861d91SShunqian Zheng {}, 827e3861d91SShunqian Zheng }; 828e3861d91SShunqian Zheng MODULE_DEVICE_TABLE(of, ov2685_of_match); 829e3861d91SShunqian Zheng #endif 830e3861d91SShunqian Zheng 831e3861d91SShunqian Zheng static struct i2c_driver ov2685_i2c_driver = { 832e3861d91SShunqian Zheng .driver = { 833e3861d91SShunqian Zheng .name = "ov2685", 834e3861d91SShunqian Zheng .owner = THIS_MODULE, 835e3861d91SShunqian Zheng .pm = &ov2685_pm_ops, 836e3861d91SShunqian Zheng .of_match_table = of_match_ptr(ov2685_of_match), 837e3861d91SShunqian Zheng }, 838e3861d91SShunqian Zheng .probe = &ov2685_probe, 839e3861d91SShunqian Zheng .remove = &ov2685_remove, 840e3861d91SShunqian Zheng }; 841e3861d91SShunqian Zheng 842e3861d91SShunqian Zheng module_i2c_driver(ov2685_i2c_driver); 843e3861d91SShunqian Zheng 844e3861d91SShunqian Zheng MODULE_DESCRIPTION("OmniVision ov2685 sensor driver"); 845e3861d91SShunqian Zheng MODULE_LICENSE("GPL v2"); 846