1*e14d3ac8SNicholas Roth // SPDX-License-Identifier: GPL-2.0 2*e14d3ac8SNicholas Roth /* 3*e14d3ac8SNicholas Roth * Copyright (C) 2023 Jacopo Mondi <jacopo.mondi@ideasonboard.com> 4*e14d3ac8SNicholas Roth * Copyright (C) 2022 Nicholas Roth <nicholas@rothemail.net> 5*e14d3ac8SNicholas Roth * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. 6*e14d3ac8SNicholas Roth */ 7*e14d3ac8SNicholas Roth 8*e14d3ac8SNicholas Roth #include <asm/unaligned.h> 9*e14d3ac8SNicholas Roth 10*e14d3ac8SNicholas Roth #include <linux/clk.h> 11*e14d3ac8SNicholas Roth #include <linux/delay.h> 12*e14d3ac8SNicholas Roth #include <linux/device.h> 13*e14d3ac8SNicholas Roth #include <linux/gpio/consumer.h> 14*e14d3ac8SNicholas Roth #include <linux/i2c.h> 15*e14d3ac8SNicholas Roth #include <linux/module.h> 16*e14d3ac8SNicholas Roth #include <linux/of.h> 17*e14d3ac8SNicholas Roth #include <linux/pm_runtime.h> 18*e14d3ac8SNicholas Roth #include <linux/property.h> 19*e14d3ac8SNicholas Roth #include <linux/regulator/consumer.h> 20*e14d3ac8SNicholas Roth #include <linux/slab.h> 21*e14d3ac8SNicholas Roth 22*e14d3ac8SNicholas Roth #include <media/media-entity.h> 23*e14d3ac8SNicholas Roth #include <media/v4l2-async.h> 24*e14d3ac8SNicholas Roth #include <media/v4l2-common.h> 25*e14d3ac8SNicholas Roth #include <media/v4l2-ctrls.h> 26*e14d3ac8SNicholas Roth #include <media/v4l2-device.h> 27*e14d3ac8SNicholas Roth #include <media/v4l2-event.h> 28*e14d3ac8SNicholas Roth #include <media/v4l2-fwnode.h> 29*e14d3ac8SNicholas Roth #include <media/v4l2-mediabus.h> 30*e14d3ac8SNicholas Roth #include <media/v4l2-subdev.h> 31*e14d3ac8SNicholas Roth 32*e14d3ac8SNicholas Roth #define OV8858_LINK_FREQ 360000000U 33*e14d3ac8SNicholas Roth #define OV8858_XVCLK_FREQ 24000000 34*e14d3ac8SNicholas Roth 35*e14d3ac8SNicholas Roth #define OV8858_REG_SIZE_SHIFT 16 36*e14d3ac8SNicholas Roth #define OV8858_REG_ADDR_MASK 0xffff 37*e14d3ac8SNicholas Roth #define OV8858_REG_8BIT(n) ((1U << OV8858_REG_SIZE_SHIFT) | (n)) 38*e14d3ac8SNicholas Roth #define OV8858_REG_16BIT(n) ((2U << OV8858_REG_SIZE_SHIFT) | (n)) 39*e14d3ac8SNicholas Roth #define OV8858_REG_24BIT(n) ((3U << OV8858_REG_SIZE_SHIFT) | (n)) 40*e14d3ac8SNicholas Roth 41*e14d3ac8SNicholas Roth #define OV8858_REG_SC_CTRL0100 OV8858_REG_8BIT(0x0100) 42*e14d3ac8SNicholas Roth #define OV8858_MODE_SW_STANDBY 0x0 43*e14d3ac8SNicholas Roth #define OV8858_MODE_STREAMING 0x1 44*e14d3ac8SNicholas Roth 45*e14d3ac8SNicholas Roth #define OV8858_REG_CHIP_ID OV8858_REG_24BIT(0x300a) 46*e14d3ac8SNicholas Roth #define OV8858_CHIP_ID 0x008858 47*e14d3ac8SNicholas Roth 48*e14d3ac8SNicholas Roth #define OV8858_REG_SUB_ID OV8858_REG_8BIT(0x302a) 49*e14d3ac8SNicholas Roth #define OV8858_R1A 0xb0 50*e14d3ac8SNicholas Roth #define OV8858_R2A 0xb2 51*e14d3ac8SNicholas Roth 52*e14d3ac8SNicholas Roth #define OV8858_REG_LONG_EXPO OV8858_REG_24BIT(0x3500) 53*e14d3ac8SNicholas Roth #define OV8858_EXPOSURE_MIN 4 54*e14d3ac8SNicholas Roth #define OV8858_EXPOSURE_STEP 1 55*e14d3ac8SNicholas Roth #define OV8858_EXPOSURE_MARGIN 4 56*e14d3ac8SNicholas Roth 57*e14d3ac8SNicholas Roth #define OV8858_REG_LONG_GAIN OV8858_REG_16BIT(0x3508) 58*e14d3ac8SNicholas Roth #define OV8858_LONG_GAIN_MIN 0x0 59*e14d3ac8SNicholas Roth #define OV8858_LONG_GAIN_MAX 0x7ff 60*e14d3ac8SNicholas Roth #define OV8858_LONG_GAIN_STEP 1 61*e14d3ac8SNicholas Roth #define OV8858_LONG_GAIN_DEFAULT 0x80 62*e14d3ac8SNicholas Roth 63*e14d3ac8SNicholas Roth #define OV8858_REG_LONG_DIGIGAIN OV8858_REG_16BIT(0x350a) 64*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_H_MASK 0x3fc0 65*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_L_MASK 0x3f 66*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_H_SHIFT 2 67*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_MIN 0x0 68*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_MAX 0x3fff 69*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_STEP 1 70*e14d3ac8SNicholas Roth #define OV8858_LONG_DIGIGAIN_DEFAULT 0x200 71*e14d3ac8SNicholas Roth 72*e14d3ac8SNicholas Roth #define OV8858_REG_VTS OV8858_REG_16BIT(0x380e) 73*e14d3ac8SNicholas Roth #define OV8858_VTS_MAX 0x7fff 74*e14d3ac8SNicholas Roth 75*e14d3ac8SNicholas Roth #define OV8858_REG_TEST_PATTERN OV8858_REG_8BIT(0x5e00) 76*e14d3ac8SNicholas Roth #define OV8858_TEST_PATTERN_ENABLE 0x80 77*e14d3ac8SNicholas Roth #define OV8858_TEST_PATTERN_DISABLE 0x0 78*e14d3ac8SNicholas Roth 79*e14d3ac8SNicholas Roth #define REG_NULL 0xffff 80*e14d3ac8SNicholas Roth 81*e14d3ac8SNicholas Roth static const char * const ov8858_supply_names[] = { 82*e14d3ac8SNicholas Roth "avdd", /* Analog power */ 83*e14d3ac8SNicholas Roth "dovdd", /* Digital I/O power */ 84*e14d3ac8SNicholas Roth "dvdd", /* Digital core power */ 85*e14d3ac8SNicholas Roth }; 86*e14d3ac8SNicholas Roth 87*e14d3ac8SNicholas Roth struct regval { 88*e14d3ac8SNicholas Roth u16 addr; 89*e14d3ac8SNicholas Roth u8 val; 90*e14d3ac8SNicholas Roth }; 91*e14d3ac8SNicholas Roth 92*e14d3ac8SNicholas Roth struct regval_modes { 93*e14d3ac8SNicholas Roth const struct regval *mode_2lanes; 94*e14d3ac8SNicholas Roth const struct regval *mode_4lanes; 95*e14d3ac8SNicholas Roth }; 96*e14d3ac8SNicholas Roth 97*e14d3ac8SNicholas Roth struct ov8858_mode { 98*e14d3ac8SNicholas Roth u32 width; 99*e14d3ac8SNicholas Roth u32 height; 100*e14d3ac8SNicholas Roth u32 hts_def; 101*e14d3ac8SNicholas Roth u32 vts_def; 102*e14d3ac8SNicholas Roth u32 exp_def; 103*e14d3ac8SNicholas Roth const struct regval_modes reg_modes; 104*e14d3ac8SNicholas Roth }; 105*e14d3ac8SNicholas Roth 106*e14d3ac8SNicholas Roth struct ov8858 { 107*e14d3ac8SNicholas Roth struct clk *xvclk; 108*e14d3ac8SNicholas Roth struct gpio_desc *reset_gpio; 109*e14d3ac8SNicholas Roth struct gpio_desc *pwdn_gpio; 110*e14d3ac8SNicholas Roth struct regulator_bulk_data supplies[ARRAY_SIZE(ov8858_supply_names)]; 111*e14d3ac8SNicholas Roth 112*e14d3ac8SNicholas Roth struct v4l2_subdev subdev; 113*e14d3ac8SNicholas Roth struct media_pad pad; 114*e14d3ac8SNicholas Roth 115*e14d3ac8SNicholas Roth struct v4l2_ctrl_handler ctrl_handler; 116*e14d3ac8SNicholas Roth struct v4l2_ctrl *exposure; 117*e14d3ac8SNicholas Roth struct v4l2_ctrl *hblank; 118*e14d3ac8SNicholas Roth struct v4l2_ctrl *vblank; 119*e14d3ac8SNicholas Roth 120*e14d3ac8SNicholas Roth const struct regval *global_regs; 121*e14d3ac8SNicholas Roth 122*e14d3ac8SNicholas Roth unsigned int num_lanes; 123*e14d3ac8SNicholas Roth }; 124*e14d3ac8SNicholas Roth 125*e14d3ac8SNicholas Roth static inline struct ov8858 *sd_to_ov8858(struct v4l2_subdev *sd) 126*e14d3ac8SNicholas Roth { 127*e14d3ac8SNicholas Roth return container_of(sd, struct ov8858, subdev); 128*e14d3ac8SNicholas Roth } 129*e14d3ac8SNicholas Roth 130*e14d3ac8SNicholas Roth static const struct regval ov8858_global_regs_r1a[] = { 131*e14d3ac8SNicholas Roth {0x0100, 0x00}, 132*e14d3ac8SNicholas Roth {0x0100, 0x00}, 133*e14d3ac8SNicholas Roth {0x0100, 0x00}, 134*e14d3ac8SNicholas Roth {0x0100, 0x00}, 135*e14d3ac8SNicholas Roth {0x0302, 0x1e}, 136*e14d3ac8SNicholas Roth {0x0303, 0x00}, 137*e14d3ac8SNicholas Roth {0x0304, 0x03}, 138*e14d3ac8SNicholas Roth {0x030e, 0x00}, 139*e14d3ac8SNicholas Roth {0x030f, 0x09}, 140*e14d3ac8SNicholas Roth {0x0312, 0x01}, 141*e14d3ac8SNicholas Roth {0x031e, 0x0c}, 142*e14d3ac8SNicholas Roth {0x3600, 0x00}, 143*e14d3ac8SNicholas Roth {0x3601, 0x00}, 144*e14d3ac8SNicholas Roth {0x3602, 0x00}, 145*e14d3ac8SNicholas Roth {0x3603, 0x00}, 146*e14d3ac8SNicholas Roth {0x3604, 0x22}, 147*e14d3ac8SNicholas Roth {0x3605, 0x30}, 148*e14d3ac8SNicholas Roth {0x3606, 0x00}, 149*e14d3ac8SNicholas Roth {0x3607, 0x20}, 150*e14d3ac8SNicholas Roth {0x3608, 0x11}, 151*e14d3ac8SNicholas Roth {0x3609, 0x28}, 152*e14d3ac8SNicholas Roth {0x360a, 0x00}, 153*e14d3ac8SNicholas Roth {0x360b, 0x06}, 154*e14d3ac8SNicholas Roth {0x360c, 0xdc}, 155*e14d3ac8SNicholas Roth {0x360d, 0x40}, 156*e14d3ac8SNicholas Roth {0x360e, 0x0c}, 157*e14d3ac8SNicholas Roth {0x360f, 0x20}, 158*e14d3ac8SNicholas Roth {0x3610, 0x07}, 159*e14d3ac8SNicholas Roth {0x3611, 0x20}, 160*e14d3ac8SNicholas Roth {0x3612, 0x88}, 161*e14d3ac8SNicholas Roth {0x3613, 0x80}, 162*e14d3ac8SNicholas Roth {0x3614, 0x58}, 163*e14d3ac8SNicholas Roth {0x3615, 0x00}, 164*e14d3ac8SNicholas Roth {0x3616, 0x4a}, 165*e14d3ac8SNicholas Roth {0x3617, 0xb0}, 166*e14d3ac8SNicholas Roth {0x3618, 0x56}, 167*e14d3ac8SNicholas Roth {0x3619, 0x70}, 168*e14d3ac8SNicholas Roth {0x361a, 0x99}, 169*e14d3ac8SNicholas Roth {0x361b, 0x00}, 170*e14d3ac8SNicholas Roth {0x361c, 0x07}, 171*e14d3ac8SNicholas Roth {0x361d, 0x00}, 172*e14d3ac8SNicholas Roth {0x361e, 0x00}, 173*e14d3ac8SNicholas Roth {0x361f, 0x00}, 174*e14d3ac8SNicholas Roth {0x3638, 0xff}, 175*e14d3ac8SNicholas Roth {0x3633, 0x0c}, 176*e14d3ac8SNicholas Roth {0x3634, 0x0c}, 177*e14d3ac8SNicholas Roth {0x3635, 0x0c}, 178*e14d3ac8SNicholas Roth {0x3636, 0x0c}, 179*e14d3ac8SNicholas Roth {0x3645, 0x13}, 180*e14d3ac8SNicholas Roth {0x3646, 0x83}, 181*e14d3ac8SNicholas Roth {0x364a, 0x07}, 182*e14d3ac8SNicholas Roth {0x3015, 0x01}, 183*e14d3ac8SNicholas Roth {0x3018, 0x32}, 184*e14d3ac8SNicholas Roth {0x3020, 0x93}, 185*e14d3ac8SNicholas Roth {0x3022, 0x01}, 186*e14d3ac8SNicholas Roth {0x3031, 0x0a}, 187*e14d3ac8SNicholas Roth {0x3034, 0x00}, 188*e14d3ac8SNicholas Roth {0x3106, 0x01}, 189*e14d3ac8SNicholas Roth {0x3305, 0xf1}, 190*e14d3ac8SNicholas Roth {0x3308, 0x00}, 191*e14d3ac8SNicholas Roth {0x3309, 0x28}, 192*e14d3ac8SNicholas Roth {0x330a, 0x00}, 193*e14d3ac8SNicholas Roth {0x330b, 0x20}, 194*e14d3ac8SNicholas Roth {0x330c, 0x00}, 195*e14d3ac8SNicholas Roth {0x330d, 0x00}, 196*e14d3ac8SNicholas Roth {0x330e, 0x00}, 197*e14d3ac8SNicholas Roth {0x330f, 0x40}, 198*e14d3ac8SNicholas Roth {0x3307, 0x04}, 199*e14d3ac8SNicholas Roth {0x3500, 0x00}, 200*e14d3ac8SNicholas Roth {0x3501, 0x4d}, 201*e14d3ac8SNicholas Roth {0x3502, 0x40}, 202*e14d3ac8SNicholas Roth {0x3503, 0x00}, 203*e14d3ac8SNicholas Roth {0x3505, 0x80}, 204*e14d3ac8SNicholas Roth {0x3508, 0x04}, 205*e14d3ac8SNicholas Roth {0x3509, 0x00}, 206*e14d3ac8SNicholas Roth {0x350c, 0x00}, 207*e14d3ac8SNicholas Roth {0x350d, 0x80}, 208*e14d3ac8SNicholas Roth {0x3510, 0x00}, 209*e14d3ac8SNicholas Roth {0x3511, 0x02}, 210*e14d3ac8SNicholas Roth {0x3512, 0x00}, 211*e14d3ac8SNicholas Roth {0x3700, 0x18}, 212*e14d3ac8SNicholas Roth {0x3701, 0x0c}, 213*e14d3ac8SNicholas Roth {0x3702, 0x28}, 214*e14d3ac8SNicholas Roth {0x3703, 0x19}, 215*e14d3ac8SNicholas Roth {0x3704, 0x14}, 216*e14d3ac8SNicholas Roth {0x3705, 0x00}, 217*e14d3ac8SNicholas Roth {0x3706, 0x35}, 218*e14d3ac8SNicholas Roth {0x3707, 0x04}, 219*e14d3ac8SNicholas Roth {0x3708, 0x24}, 220*e14d3ac8SNicholas Roth {0x3709, 0x33}, 221*e14d3ac8SNicholas Roth {0x370a, 0x00}, 222*e14d3ac8SNicholas Roth {0x370b, 0xb5}, 223*e14d3ac8SNicholas Roth {0x370c, 0x04}, 224*e14d3ac8SNicholas Roth {0x3718, 0x12}, 225*e14d3ac8SNicholas Roth {0x3719, 0x31}, 226*e14d3ac8SNicholas Roth {0x3712, 0x42}, 227*e14d3ac8SNicholas Roth {0x3714, 0x24}, 228*e14d3ac8SNicholas Roth {0x371e, 0x19}, 229*e14d3ac8SNicholas Roth {0x371f, 0x40}, 230*e14d3ac8SNicholas Roth {0x3720, 0x05}, 231*e14d3ac8SNicholas Roth {0x3721, 0x05}, 232*e14d3ac8SNicholas Roth {0x3724, 0x06}, 233*e14d3ac8SNicholas Roth {0x3725, 0x01}, 234*e14d3ac8SNicholas Roth {0x3726, 0x06}, 235*e14d3ac8SNicholas Roth {0x3728, 0x05}, 236*e14d3ac8SNicholas Roth {0x3729, 0x02}, 237*e14d3ac8SNicholas Roth {0x372a, 0x03}, 238*e14d3ac8SNicholas Roth {0x372b, 0x53}, 239*e14d3ac8SNicholas Roth {0x372c, 0xa3}, 240*e14d3ac8SNicholas Roth {0x372d, 0x53}, 241*e14d3ac8SNicholas Roth {0x372e, 0x06}, 242*e14d3ac8SNicholas Roth {0x372f, 0x10}, 243*e14d3ac8SNicholas Roth {0x3730, 0x01}, 244*e14d3ac8SNicholas Roth {0x3731, 0x06}, 245*e14d3ac8SNicholas Roth {0x3732, 0x14}, 246*e14d3ac8SNicholas Roth {0x3733, 0x10}, 247*e14d3ac8SNicholas Roth {0x3734, 0x40}, 248*e14d3ac8SNicholas Roth {0x3736, 0x20}, 249*e14d3ac8SNicholas Roth {0x373a, 0x05}, 250*e14d3ac8SNicholas Roth {0x373b, 0x06}, 251*e14d3ac8SNicholas Roth {0x373c, 0x0a}, 252*e14d3ac8SNicholas Roth {0x373e, 0x03}, 253*e14d3ac8SNicholas Roth {0x3755, 0x10}, 254*e14d3ac8SNicholas Roth {0x3758, 0x00}, 255*e14d3ac8SNicholas Roth {0x3759, 0x4c}, 256*e14d3ac8SNicholas Roth {0x375a, 0x06}, 257*e14d3ac8SNicholas Roth {0x375b, 0x13}, 258*e14d3ac8SNicholas Roth {0x375c, 0x20}, 259*e14d3ac8SNicholas Roth {0x375d, 0x02}, 260*e14d3ac8SNicholas Roth {0x375e, 0x00}, 261*e14d3ac8SNicholas Roth {0x375f, 0x14}, 262*e14d3ac8SNicholas Roth {0x3768, 0x22}, 263*e14d3ac8SNicholas Roth {0x3769, 0x44}, 264*e14d3ac8SNicholas Roth {0x376a, 0x44}, 265*e14d3ac8SNicholas Roth {0x3761, 0x00}, 266*e14d3ac8SNicholas Roth {0x3762, 0x00}, 267*e14d3ac8SNicholas Roth {0x3763, 0x00}, 268*e14d3ac8SNicholas Roth {0x3766, 0xff}, 269*e14d3ac8SNicholas Roth {0x376b, 0x00}, 270*e14d3ac8SNicholas Roth {0x3772, 0x23}, 271*e14d3ac8SNicholas Roth {0x3773, 0x02}, 272*e14d3ac8SNicholas Roth {0x3774, 0x16}, 273*e14d3ac8SNicholas Roth {0x3775, 0x12}, 274*e14d3ac8SNicholas Roth {0x3776, 0x04}, 275*e14d3ac8SNicholas Roth {0x3777, 0x00}, 276*e14d3ac8SNicholas Roth {0x3778, 0x1b}, 277*e14d3ac8SNicholas Roth {0x37a0, 0x44}, 278*e14d3ac8SNicholas Roth {0x37a1, 0x3d}, 279*e14d3ac8SNicholas Roth {0x37a2, 0x3d}, 280*e14d3ac8SNicholas Roth {0x37a3, 0x00}, 281*e14d3ac8SNicholas Roth {0x37a4, 0x00}, 282*e14d3ac8SNicholas Roth {0x37a5, 0x00}, 283*e14d3ac8SNicholas Roth {0x37a6, 0x00}, 284*e14d3ac8SNicholas Roth {0x37a7, 0x44}, 285*e14d3ac8SNicholas Roth {0x37a8, 0x4c}, 286*e14d3ac8SNicholas Roth {0x37a9, 0x4c}, 287*e14d3ac8SNicholas Roth {0x3760, 0x00}, 288*e14d3ac8SNicholas Roth {0x376f, 0x01}, 289*e14d3ac8SNicholas Roth {0x37aa, 0x44}, 290*e14d3ac8SNicholas Roth {0x37ab, 0x2e}, 291*e14d3ac8SNicholas Roth {0x37ac, 0x2e}, 292*e14d3ac8SNicholas Roth {0x37ad, 0x33}, 293*e14d3ac8SNicholas Roth {0x37ae, 0x0d}, 294*e14d3ac8SNicholas Roth {0x37af, 0x0d}, 295*e14d3ac8SNicholas Roth {0x37b0, 0x00}, 296*e14d3ac8SNicholas Roth {0x37b1, 0x00}, 297*e14d3ac8SNicholas Roth {0x37b2, 0x00}, 298*e14d3ac8SNicholas Roth {0x37b3, 0x42}, 299*e14d3ac8SNicholas Roth {0x37b4, 0x42}, 300*e14d3ac8SNicholas Roth {0x37b5, 0x33}, 301*e14d3ac8SNicholas Roth {0x37b6, 0x00}, 302*e14d3ac8SNicholas Roth {0x37b7, 0x00}, 303*e14d3ac8SNicholas Roth {0x37b8, 0x00}, 304*e14d3ac8SNicholas Roth {0x37b9, 0xff}, 305*e14d3ac8SNicholas Roth {0x3800, 0x00}, 306*e14d3ac8SNicholas Roth {0x3801, 0x0c}, 307*e14d3ac8SNicholas Roth {0x3802, 0x00}, 308*e14d3ac8SNicholas Roth {0x3803, 0x0c}, 309*e14d3ac8SNicholas Roth {0x3804, 0x0c}, 310*e14d3ac8SNicholas Roth {0x3805, 0xd3}, 311*e14d3ac8SNicholas Roth {0x3806, 0x09}, 312*e14d3ac8SNicholas Roth {0x3807, 0xa3}, 313*e14d3ac8SNicholas Roth {0x3808, 0x06}, 314*e14d3ac8SNicholas Roth {0x3809, 0x60}, 315*e14d3ac8SNicholas Roth {0x380a, 0x04}, 316*e14d3ac8SNicholas Roth {0x380b, 0xc8}, 317*e14d3ac8SNicholas Roth {0x380c, 0x07}, 318*e14d3ac8SNicholas Roth {0x380d, 0x88}, 319*e14d3ac8SNicholas Roth {0x380e, 0x04}, 320*e14d3ac8SNicholas Roth {0x380f, 0xdc}, 321*e14d3ac8SNicholas Roth {0x3810, 0x00}, 322*e14d3ac8SNicholas Roth {0x3811, 0x04}, 323*e14d3ac8SNicholas Roth {0x3813, 0x02}, 324*e14d3ac8SNicholas Roth {0x3814, 0x03}, 325*e14d3ac8SNicholas Roth {0x3815, 0x01}, 326*e14d3ac8SNicholas Roth {0x3820, 0x00}, 327*e14d3ac8SNicholas Roth {0x3821, 0x67}, 328*e14d3ac8SNicholas Roth {0x382a, 0x03}, 329*e14d3ac8SNicholas Roth {0x382b, 0x01}, 330*e14d3ac8SNicholas Roth {0x3830, 0x08}, 331*e14d3ac8SNicholas Roth {0x3836, 0x02}, 332*e14d3ac8SNicholas Roth {0x3837, 0x18}, 333*e14d3ac8SNicholas Roth {0x3841, 0xff}, 334*e14d3ac8SNicholas Roth {0x3846, 0x48}, 335*e14d3ac8SNicholas Roth {0x3d85, 0x14}, 336*e14d3ac8SNicholas Roth {0x3f08, 0x08}, 337*e14d3ac8SNicholas Roth {0x3f0a, 0x80}, 338*e14d3ac8SNicholas Roth {0x4000, 0xf1}, 339*e14d3ac8SNicholas Roth {0x4001, 0x10}, 340*e14d3ac8SNicholas Roth {0x4005, 0x10}, 341*e14d3ac8SNicholas Roth {0x4002, 0x27}, 342*e14d3ac8SNicholas Roth {0x4009, 0x81}, 343*e14d3ac8SNicholas Roth {0x400b, 0x0c}, 344*e14d3ac8SNicholas Roth {0x401b, 0x00}, 345*e14d3ac8SNicholas Roth {0x401d, 0x00}, 346*e14d3ac8SNicholas Roth {0x4020, 0x00}, 347*e14d3ac8SNicholas Roth {0x4021, 0x04}, 348*e14d3ac8SNicholas Roth {0x4022, 0x04}, 349*e14d3ac8SNicholas Roth {0x4023, 0xb9}, 350*e14d3ac8SNicholas Roth {0x4024, 0x05}, 351*e14d3ac8SNicholas Roth {0x4025, 0x2a}, 352*e14d3ac8SNicholas Roth {0x4026, 0x05}, 353*e14d3ac8SNicholas Roth {0x4027, 0x2b}, 354*e14d3ac8SNicholas Roth {0x4028, 0x00}, 355*e14d3ac8SNicholas Roth {0x4029, 0x02}, 356*e14d3ac8SNicholas Roth {0x402a, 0x04}, 357*e14d3ac8SNicholas Roth {0x402b, 0x04}, 358*e14d3ac8SNicholas Roth {0x402c, 0x02}, 359*e14d3ac8SNicholas Roth {0x402d, 0x02}, 360*e14d3ac8SNicholas Roth {0x402e, 0x08}, 361*e14d3ac8SNicholas Roth {0x402f, 0x02}, 362*e14d3ac8SNicholas Roth {0x401f, 0x00}, 363*e14d3ac8SNicholas Roth {0x4034, 0x3f}, 364*e14d3ac8SNicholas Roth {0x403d, 0x04}, 365*e14d3ac8SNicholas Roth {0x4300, 0xff}, 366*e14d3ac8SNicholas Roth {0x4301, 0x00}, 367*e14d3ac8SNicholas Roth {0x4302, 0x0f}, 368*e14d3ac8SNicholas Roth {0x4316, 0x00}, 369*e14d3ac8SNicholas Roth {0x4500, 0x38}, 370*e14d3ac8SNicholas Roth {0x4503, 0x18}, 371*e14d3ac8SNicholas Roth {0x4600, 0x00}, 372*e14d3ac8SNicholas Roth {0x4601, 0xcb}, 373*e14d3ac8SNicholas Roth {0x481f, 0x32}, 374*e14d3ac8SNicholas Roth {0x4837, 0x16}, 375*e14d3ac8SNicholas Roth {0x4850, 0x10}, 376*e14d3ac8SNicholas Roth {0x4851, 0x32}, 377*e14d3ac8SNicholas Roth {0x4b00, 0x2a}, 378*e14d3ac8SNicholas Roth {0x4b0d, 0x00}, 379*e14d3ac8SNicholas Roth {0x4d00, 0x04}, 380*e14d3ac8SNicholas Roth {0x4d01, 0x18}, 381*e14d3ac8SNicholas Roth {0x4d02, 0xc3}, 382*e14d3ac8SNicholas Roth {0x4d03, 0xff}, 383*e14d3ac8SNicholas Roth {0x4d04, 0xff}, 384*e14d3ac8SNicholas Roth {0x4d05, 0xff}, 385*e14d3ac8SNicholas Roth {0x5000, 0x7e}, 386*e14d3ac8SNicholas Roth {0x5001, 0x01}, 387*e14d3ac8SNicholas Roth {0x5002, 0x08}, 388*e14d3ac8SNicholas Roth {0x5003, 0x20}, 389*e14d3ac8SNicholas Roth {0x5046, 0x12}, 390*e14d3ac8SNicholas Roth {0x5901, 0x00}, 391*e14d3ac8SNicholas Roth {0x5e00, 0x00}, 392*e14d3ac8SNicholas Roth {0x5e01, 0x41}, 393*e14d3ac8SNicholas Roth {0x382d, 0x7f}, 394*e14d3ac8SNicholas Roth {0x4825, 0x3a}, 395*e14d3ac8SNicholas Roth {0x4826, 0x40}, 396*e14d3ac8SNicholas Roth {0x4808, 0x25}, 397*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 398*e14d3ac8SNicholas Roth }; 399*e14d3ac8SNicholas Roth 400*e14d3ac8SNicholas Roth static const struct regval ov8858_global_regs_r2a_2lane[] = { 401*e14d3ac8SNicholas Roth /* 402*e14d3ac8SNicholas Roth * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz. 403*e14d3ac8SNicholas Roth * v00_01_00 (05/29/2014) : initial setting 404*e14d3ac8SNicholas Roth * AM19 : 3617 <- 0xC0 405*e14d3ac8SNicholas Roth * AM20 : change FWC_6K_EN to be default 0x3618=0x5a 406*e14d3ac8SNicholas Roth */ 407*e14d3ac8SNicholas Roth {0x0103, 0x01}, /* software reset */ 408*e14d3ac8SNicholas Roth {0x0100, 0x00}, /* software standby */ 409*e14d3ac8SNicholas Roth {0x0302, 0x1e}, /* pll1_multi */ 410*e14d3ac8SNicholas Roth {0x0303, 0x00}, /* pll1_divm */ 411*e14d3ac8SNicholas Roth {0x0304, 0x03}, /* pll1_div_mipi */ 412*e14d3ac8SNicholas Roth {0x030e, 0x02}, /* pll2_rdiv */ 413*e14d3ac8SNicholas Roth {0x030f, 0x04}, /* pll2_divsp */ 414*e14d3ac8SNicholas Roth {0x0312, 0x03}, /* pll2_pre_div0, pll2_r_divdac */ 415*e14d3ac8SNicholas Roth {0x031e, 0x0c}, /* pll1_no_lat */ 416*e14d3ac8SNicholas Roth {0x3600, 0x00}, 417*e14d3ac8SNicholas Roth {0x3601, 0x00}, 418*e14d3ac8SNicholas Roth {0x3602, 0x00}, 419*e14d3ac8SNicholas Roth {0x3603, 0x00}, 420*e14d3ac8SNicholas Roth {0x3604, 0x22}, 421*e14d3ac8SNicholas Roth {0x3605, 0x20}, 422*e14d3ac8SNicholas Roth {0x3606, 0x00}, 423*e14d3ac8SNicholas Roth {0x3607, 0x20}, 424*e14d3ac8SNicholas Roth {0x3608, 0x11}, 425*e14d3ac8SNicholas Roth {0x3609, 0x28}, 426*e14d3ac8SNicholas Roth {0x360a, 0x00}, 427*e14d3ac8SNicholas Roth {0x360b, 0x05}, 428*e14d3ac8SNicholas Roth {0x360c, 0xd4}, 429*e14d3ac8SNicholas Roth {0x360d, 0x40}, 430*e14d3ac8SNicholas Roth {0x360e, 0x0c}, 431*e14d3ac8SNicholas Roth {0x360f, 0x20}, 432*e14d3ac8SNicholas Roth {0x3610, 0x07}, 433*e14d3ac8SNicholas Roth {0x3611, 0x20}, 434*e14d3ac8SNicholas Roth {0x3612, 0x88}, 435*e14d3ac8SNicholas Roth {0x3613, 0x80}, 436*e14d3ac8SNicholas Roth {0x3614, 0x58}, 437*e14d3ac8SNicholas Roth {0x3615, 0x00}, 438*e14d3ac8SNicholas Roth {0x3616, 0x4a}, 439*e14d3ac8SNicholas Roth {0x3617, 0x90}, 440*e14d3ac8SNicholas Roth {0x3618, 0x5a}, 441*e14d3ac8SNicholas Roth {0x3619, 0x70}, 442*e14d3ac8SNicholas Roth {0x361a, 0x99}, 443*e14d3ac8SNicholas Roth {0x361b, 0x0a}, 444*e14d3ac8SNicholas Roth {0x361c, 0x07}, 445*e14d3ac8SNicholas Roth {0x361d, 0x00}, 446*e14d3ac8SNicholas Roth {0x361e, 0x00}, 447*e14d3ac8SNicholas Roth {0x361f, 0x00}, 448*e14d3ac8SNicholas Roth {0x3638, 0xff}, 449*e14d3ac8SNicholas Roth {0x3633, 0x0f}, 450*e14d3ac8SNicholas Roth {0x3634, 0x0f}, 451*e14d3ac8SNicholas Roth {0x3635, 0x0f}, 452*e14d3ac8SNicholas Roth {0x3636, 0x12}, 453*e14d3ac8SNicholas Roth {0x3645, 0x13}, 454*e14d3ac8SNicholas Roth {0x3646, 0x83}, 455*e14d3ac8SNicholas Roth {0x364a, 0x07}, 456*e14d3ac8SNicholas Roth {0x3015, 0x00}, 457*e14d3ac8SNicholas Roth {0x3018, 0x32}, /* MIPI 2 lane */ 458*e14d3ac8SNicholas Roth {0x3020, 0x93}, /* Clock switch output normal, pclk_div =/1 */ 459*e14d3ac8SNicholas Roth {0x3022, 0x01}, /* pd_mipi enable when rst_sync */ 460*e14d3ac8SNicholas Roth {0x3031, 0x0a}, /* MIPI 10-bit mode */ 461*e14d3ac8SNicholas Roth {0x3034, 0x00}, 462*e14d3ac8SNicholas Roth {0x3106, 0x01}, /* sclk_div, sclk_pre_div */ 463*e14d3ac8SNicholas Roth {0x3305, 0xf1}, 464*e14d3ac8SNicholas Roth {0x3308, 0x00}, 465*e14d3ac8SNicholas Roth {0x3309, 0x28}, 466*e14d3ac8SNicholas Roth {0x330a, 0x00}, 467*e14d3ac8SNicholas Roth {0x330b, 0x20}, 468*e14d3ac8SNicholas Roth {0x330c, 0x00}, 469*e14d3ac8SNicholas Roth {0x330d, 0x00}, 470*e14d3ac8SNicholas Roth {0x330e, 0x00}, 471*e14d3ac8SNicholas Roth {0x330f, 0x40}, 472*e14d3ac8SNicholas Roth {0x3307, 0x04}, 473*e14d3ac8SNicholas Roth {0x3500, 0x00}, /* exposure H */ 474*e14d3ac8SNicholas Roth {0x3501, 0x4d}, /* exposure M */ 475*e14d3ac8SNicholas Roth {0x3502, 0x40}, /* exposure L */ 476*e14d3ac8SNicholas Roth {0x3503, 0x80}, /* gain delay ?, exposure delay 1 frame, real gain */ 477*e14d3ac8SNicholas Roth {0x3505, 0x80}, /* gain option */ 478*e14d3ac8SNicholas Roth {0x3508, 0x02}, /* gain H */ 479*e14d3ac8SNicholas Roth {0x3509, 0x00}, /* gain L */ 480*e14d3ac8SNicholas Roth {0x350c, 0x00}, /* short gain H */ 481*e14d3ac8SNicholas Roth {0x350d, 0x80}, /* short gain L */ 482*e14d3ac8SNicholas Roth {0x3510, 0x00}, /* short exposure H */ 483*e14d3ac8SNicholas Roth {0x3511, 0x02}, /* short exposure M */ 484*e14d3ac8SNicholas Roth {0x3512, 0x00}, /* short exposure L */ 485*e14d3ac8SNicholas Roth {0x3700, 0x18}, 486*e14d3ac8SNicholas Roth {0x3701, 0x0c}, 487*e14d3ac8SNicholas Roth {0x3702, 0x28}, 488*e14d3ac8SNicholas Roth {0x3703, 0x19}, 489*e14d3ac8SNicholas Roth {0x3704, 0x14}, 490*e14d3ac8SNicholas Roth {0x3705, 0x00}, 491*e14d3ac8SNicholas Roth {0x3706, 0x82}, 492*e14d3ac8SNicholas Roth {0x3707, 0x04}, 493*e14d3ac8SNicholas Roth {0x3708, 0x24}, 494*e14d3ac8SNicholas Roth {0x3709, 0x33}, 495*e14d3ac8SNicholas Roth {0x370a, 0x01}, 496*e14d3ac8SNicholas Roth {0x370b, 0x82}, 497*e14d3ac8SNicholas Roth {0x370c, 0x04}, 498*e14d3ac8SNicholas Roth {0x3718, 0x12}, 499*e14d3ac8SNicholas Roth {0x3719, 0x31}, 500*e14d3ac8SNicholas Roth {0x3712, 0x42}, 501*e14d3ac8SNicholas Roth {0x3714, 0x24}, 502*e14d3ac8SNicholas Roth {0x371e, 0x19}, 503*e14d3ac8SNicholas Roth {0x371f, 0x40}, 504*e14d3ac8SNicholas Roth {0x3720, 0x05}, 505*e14d3ac8SNicholas Roth {0x3721, 0x05}, 506*e14d3ac8SNicholas Roth {0x3724, 0x06}, 507*e14d3ac8SNicholas Roth {0x3725, 0x01}, 508*e14d3ac8SNicholas Roth {0x3726, 0x06}, 509*e14d3ac8SNicholas Roth {0x3728, 0x05}, 510*e14d3ac8SNicholas Roth {0x3729, 0x02}, 511*e14d3ac8SNicholas Roth {0x372a, 0x03}, 512*e14d3ac8SNicholas Roth {0x372b, 0x53}, 513*e14d3ac8SNicholas Roth {0x372c, 0xa3}, 514*e14d3ac8SNicholas Roth {0x372d, 0x53}, 515*e14d3ac8SNicholas Roth {0x372e, 0x06}, 516*e14d3ac8SNicholas Roth {0x372f, 0x10}, 517*e14d3ac8SNicholas Roth {0x3730, 0x01}, 518*e14d3ac8SNicholas Roth {0x3731, 0x06}, 519*e14d3ac8SNicholas Roth {0x3732, 0x14}, 520*e14d3ac8SNicholas Roth {0x3733, 0x10}, 521*e14d3ac8SNicholas Roth {0x3734, 0x40}, 522*e14d3ac8SNicholas Roth {0x3736, 0x20}, 523*e14d3ac8SNicholas Roth {0x373a, 0x05}, 524*e14d3ac8SNicholas Roth {0x373b, 0x06}, 525*e14d3ac8SNicholas Roth {0x373c, 0x0a}, 526*e14d3ac8SNicholas Roth {0x373e, 0x03}, 527*e14d3ac8SNicholas Roth {0x3750, 0x0a}, 528*e14d3ac8SNicholas Roth {0x3751, 0x0e}, 529*e14d3ac8SNicholas Roth {0x3755, 0x10}, 530*e14d3ac8SNicholas Roth {0x3758, 0x00}, 531*e14d3ac8SNicholas Roth {0x3759, 0x4c}, 532*e14d3ac8SNicholas Roth {0x375a, 0x06}, 533*e14d3ac8SNicholas Roth {0x375b, 0x13}, 534*e14d3ac8SNicholas Roth {0x375c, 0x20}, 535*e14d3ac8SNicholas Roth {0x375d, 0x02}, 536*e14d3ac8SNicholas Roth {0x375e, 0x00}, 537*e14d3ac8SNicholas Roth {0x375f, 0x14}, 538*e14d3ac8SNicholas Roth {0x3768, 0x22}, 539*e14d3ac8SNicholas Roth {0x3769, 0x44}, 540*e14d3ac8SNicholas Roth {0x376a, 0x44}, 541*e14d3ac8SNicholas Roth {0x3761, 0x00}, 542*e14d3ac8SNicholas Roth {0x3762, 0x00}, 543*e14d3ac8SNicholas Roth {0x3763, 0x00}, 544*e14d3ac8SNicholas Roth {0x3766, 0xff}, 545*e14d3ac8SNicholas Roth {0x376b, 0x00}, 546*e14d3ac8SNicholas Roth {0x3772, 0x23}, 547*e14d3ac8SNicholas Roth {0x3773, 0x02}, 548*e14d3ac8SNicholas Roth {0x3774, 0x16}, 549*e14d3ac8SNicholas Roth {0x3775, 0x12}, 550*e14d3ac8SNicholas Roth {0x3776, 0x04}, 551*e14d3ac8SNicholas Roth {0x3777, 0x00}, 552*e14d3ac8SNicholas Roth {0x3778, 0x17}, 553*e14d3ac8SNicholas Roth {0x37a0, 0x44}, 554*e14d3ac8SNicholas Roth {0x37a1, 0x3d}, 555*e14d3ac8SNicholas Roth {0x37a2, 0x3d}, 556*e14d3ac8SNicholas Roth {0x37a3, 0x00}, 557*e14d3ac8SNicholas Roth {0x37a4, 0x00}, 558*e14d3ac8SNicholas Roth {0x37a5, 0x00}, 559*e14d3ac8SNicholas Roth {0x37a6, 0x00}, 560*e14d3ac8SNicholas Roth {0x37a7, 0x44}, 561*e14d3ac8SNicholas Roth {0x37a8, 0x4c}, 562*e14d3ac8SNicholas Roth {0x37a9, 0x4c}, 563*e14d3ac8SNicholas Roth {0x3760, 0x00}, 564*e14d3ac8SNicholas Roth {0x376f, 0x01}, 565*e14d3ac8SNicholas Roth {0x37aa, 0x44}, 566*e14d3ac8SNicholas Roth {0x37ab, 0x2e}, 567*e14d3ac8SNicholas Roth {0x37ac, 0x2e}, 568*e14d3ac8SNicholas Roth {0x37ad, 0x33}, 569*e14d3ac8SNicholas Roth {0x37ae, 0x0d}, 570*e14d3ac8SNicholas Roth {0x37af, 0x0d}, 571*e14d3ac8SNicholas Roth {0x37b0, 0x00}, 572*e14d3ac8SNicholas Roth {0x37b1, 0x00}, 573*e14d3ac8SNicholas Roth {0x37b2, 0x00}, 574*e14d3ac8SNicholas Roth {0x37b3, 0x42}, 575*e14d3ac8SNicholas Roth {0x37b4, 0x42}, 576*e14d3ac8SNicholas Roth {0x37b5, 0x31}, 577*e14d3ac8SNicholas Roth {0x37b6, 0x00}, 578*e14d3ac8SNicholas Roth {0x37b7, 0x00}, 579*e14d3ac8SNicholas Roth {0x37b8, 0x00}, 580*e14d3ac8SNicholas Roth {0x37b9, 0xff}, 581*e14d3ac8SNicholas Roth {0x3800, 0x00}, /* x start H */ 582*e14d3ac8SNicholas Roth {0x3801, 0x0c}, /* x start L */ 583*e14d3ac8SNicholas Roth {0x3802, 0x00}, /* y start H */ 584*e14d3ac8SNicholas Roth {0x3803, 0x0c}, /* y start L */ 585*e14d3ac8SNicholas Roth {0x3804, 0x0c}, /* x end H */ 586*e14d3ac8SNicholas Roth {0x3805, 0xd3}, /* x end L */ 587*e14d3ac8SNicholas Roth {0x3806, 0x09}, /* y end H */ 588*e14d3ac8SNicholas Roth {0x3807, 0xa3}, /* y end L */ 589*e14d3ac8SNicholas Roth {0x3808, 0x06}, /* x output size H */ 590*e14d3ac8SNicholas Roth {0x3809, 0x60}, /* x output size L */ 591*e14d3ac8SNicholas Roth {0x380a, 0x04}, /* y output size H */ 592*e14d3ac8SNicholas Roth {0x380b, 0xc8}, /* y output size L */ 593*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 594*e14d3ac8SNicholas Roth {0x380d, 0x88}, /* HTS L */ 595*e14d3ac8SNicholas Roth {0x380e, 0x04}, /* VTS H */ 596*e14d3ac8SNicholas Roth {0x380f, 0xdc}, /* VTS L */ 597*e14d3ac8SNicholas Roth {0x3810, 0x00}, /* ISP x win H */ 598*e14d3ac8SNicholas Roth {0x3811, 0x04}, /* ISP x win L */ 599*e14d3ac8SNicholas Roth {0x3813, 0x02}, /* ISP y win L */ 600*e14d3ac8SNicholas Roth {0x3814, 0x03}, /* x odd inc */ 601*e14d3ac8SNicholas Roth {0x3815, 0x01}, /* x even inc */ 602*e14d3ac8SNicholas Roth {0x3820, 0x00}, /* vflip off */ 603*e14d3ac8SNicholas Roth {0x3821, 0x67}, /* mirror on, bin on */ 604*e14d3ac8SNicholas Roth {0x382a, 0x03}, /* y odd inc */ 605*e14d3ac8SNicholas Roth {0x382b, 0x01}, /* y even inc */ 606*e14d3ac8SNicholas Roth {0x3830, 0x08}, 607*e14d3ac8SNicholas Roth {0x3836, 0x02}, 608*e14d3ac8SNicholas Roth {0x3837, 0x18}, 609*e14d3ac8SNicholas Roth {0x3841, 0xff}, /* window auto size enable */ 610*e14d3ac8SNicholas Roth {0x3846, 0x48}, 611*e14d3ac8SNicholas Roth {0x3d85, 0x16}, /* OTP power up load data enable with BIST */ 612*e14d3ac8SNicholas Roth {0x3d8c, 0x73}, /* OTP setting start High */ 613*e14d3ac8SNicholas Roth {0x3d8d, 0xde}, /* OTP setting start Low */ 614*e14d3ac8SNicholas Roth {0x3f08, 0x08}, 615*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 616*e14d3ac8SNicholas Roth {0x4000, 0xf1}, /* out_range_trig, format_chg_trig */ 617*e14d3ac8SNicholas Roth {0x4001, 0x10}, /* total 128 black column */ 618*e14d3ac8SNicholas Roth {0x4005, 0x10}, /* BLC target L */ 619*e14d3ac8SNicholas Roth {0x4002, 0x27}, /* value used to limit BLC offset */ 620*e14d3ac8SNicholas Roth {0x4009, 0x81}, /* final BLC offset limitation enable */ 621*e14d3ac8SNicholas Roth {0x400b, 0x0c}, /* DCBLC on, DCBLC manual mode on */ 622*e14d3ac8SNicholas Roth {0x401b, 0x00}, /* zero line R coefficient */ 623*e14d3ac8SNicholas Roth {0x401d, 0x00}, /* zoro line T coefficient */ 624*e14d3ac8SNicholas Roth {0x4020, 0x00}, /* Anchor left start H */ 625*e14d3ac8SNicholas Roth {0x4021, 0x04}, /* Anchor left start L */ 626*e14d3ac8SNicholas Roth {0x4022, 0x06}, /* Anchor left end H */ 627*e14d3ac8SNicholas Roth {0x4023, 0x00}, /* Anchor left end L */ 628*e14d3ac8SNicholas Roth {0x4024, 0x0f}, /* Anchor right start H */ 629*e14d3ac8SNicholas Roth {0x4025, 0x2a}, /* Anchor right start L */ 630*e14d3ac8SNicholas Roth {0x4026, 0x0f}, /* Anchor right end H */ 631*e14d3ac8SNicholas Roth {0x4027, 0x2b}, /* Anchor right end L */ 632*e14d3ac8SNicholas Roth {0x4028, 0x00}, /* top zero line start */ 633*e14d3ac8SNicholas Roth {0x4029, 0x02}, /* top zero line number */ 634*e14d3ac8SNicholas Roth {0x402a, 0x04}, /* top black line start */ 635*e14d3ac8SNicholas Roth {0x402b, 0x04}, /* top black line number */ 636*e14d3ac8SNicholas Roth {0x402c, 0x00}, /* bottom zero line start */ 637*e14d3ac8SNicholas Roth {0x402d, 0x02}, /* bottom zoro line number */ 638*e14d3ac8SNicholas Roth {0x402e, 0x04}, /* bottom black line start */ 639*e14d3ac8SNicholas Roth {0x402f, 0x04}, /* bottom black line number */ 640*e14d3ac8SNicholas Roth {0x401f, 0x00}, /* interpolation x/y disable, Anchor one disable */ 641*e14d3ac8SNicholas Roth {0x4034, 0x3f}, 642*e14d3ac8SNicholas Roth {0x403d, 0x04}, /* md_precision_en */ 643*e14d3ac8SNicholas Roth {0x4300, 0xff}, /* clip max H */ 644*e14d3ac8SNicholas Roth {0x4301, 0x00}, /* clip min H */ 645*e14d3ac8SNicholas Roth {0x4302, 0x0f}, /* clip min L, clip max L */ 646*e14d3ac8SNicholas Roth {0x4316, 0x00}, 647*e14d3ac8SNicholas Roth {0x4500, 0x58}, 648*e14d3ac8SNicholas Roth {0x4503, 0x18}, 649*e14d3ac8SNicholas Roth {0x4600, 0x00}, 650*e14d3ac8SNicholas Roth {0x4601, 0xcb}, 651*e14d3ac8SNicholas Roth {0x481f, 0x32}, /* clk prepare min */ 652*e14d3ac8SNicholas Roth {0x4837, 0x16}, /* global timing */ 653*e14d3ac8SNicholas Roth {0x4850, 0x10}, /* lane 1 = 1, lane 0 = 0 */ 654*e14d3ac8SNicholas Roth {0x4851, 0x32}, /* lane 3 = 3, lane 2 = 2 */ 655*e14d3ac8SNicholas Roth {0x4b00, 0x2a}, 656*e14d3ac8SNicholas Roth {0x4b0d, 0x00}, 657*e14d3ac8SNicholas Roth {0x4d00, 0x04}, /* temperature sensor */ 658*e14d3ac8SNicholas Roth {0x4d01, 0x18}, 659*e14d3ac8SNicholas Roth {0x4d02, 0xc3}, 660*e14d3ac8SNicholas Roth {0x4d03, 0xff}, 661*e14d3ac8SNicholas Roth {0x4d04, 0xff}, 662*e14d3ac8SNicholas Roth {0x4d05, 0xff}, /* temperature sensor */ 663*e14d3ac8SNicholas Roth {0x5000, 0xfe}, /* lenc on, slave/master AWB gain/statistics enable */ 664*e14d3ac8SNicholas Roth {0x5001, 0x01}, /* BLC on */ 665*e14d3ac8SNicholas Roth {0x5002, 0x08}, /* H scale off, WBMATCH off, OTP_DPC */ 666*e14d3ac8SNicholas Roth {0x5003, 0x20}, /* DPC_DBC buffer control enable, WB */ 667*e14d3ac8SNicholas Roth {0x501e, 0x93}, /* enable digital gain */ 668*e14d3ac8SNicholas Roth {0x5046, 0x12}, 669*e14d3ac8SNicholas Roth {0x5780, 0x3e}, /* DPC */ 670*e14d3ac8SNicholas Roth {0x5781, 0x0f}, 671*e14d3ac8SNicholas Roth {0x5782, 0x44}, 672*e14d3ac8SNicholas Roth {0x5783, 0x02}, 673*e14d3ac8SNicholas Roth {0x5784, 0x01}, 674*e14d3ac8SNicholas Roth {0x5785, 0x00}, 675*e14d3ac8SNicholas Roth {0x5786, 0x00}, 676*e14d3ac8SNicholas Roth {0x5787, 0x04}, 677*e14d3ac8SNicholas Roth {0x5788, 0x02}, 678*e14d3ac8SNicholas Roth {0x5789, 0x0f}, 679*e14d3ac8SNicholas Roth {0x578a, 0xfd}, 680*e14d3ac8SNicholas Roth {0x578b, 0xf5}, 681*e14d3ac8SNicholas Roth {0x578c, 0xf5}, 682*e14d3ac8SNicholas Roth {0x578d, 0x03}, 683*e14d3ac8SNicholas Roth {0x578e, 0x08}, 684*e14d3ac8SNicholas Roth {0x578f, 0x0c}, 685*e14d3ac8SNicholas Roth {0x5790, 0x08}, 686*e14d3ac8SNicholas Roth {0x5791, 0x04}, 687*e14d3ac8SNicholas Roth {0x5792, 0x00}, 688*e14d3ac8SNicholas Roth {0x5793, 0x52}, 689*e14d3ac8SNicholas Roth {0x5794, 0xa3}, /* DPC */ 690*e14d3ac8SNicholas Roth {0x5871, 0x0d}, /* Lenc */ 691*e14d3ac8SNicholas Roth {0x5870, 0x18}, 692*e14d3ac8SNicholas Roth {0x586e, 0x10}, 693*e14d3ac8SNicholas Roth {0x586f, 0x08}, 694*e14d3ac8SNicholas Roth {0x58f7, 0x01}, 695*e14d3ac8SNicholas Roth {0x58f8, 0x3d}, /* Lenc */ 696*e14d3ac8SNicholas Roth {0x5901, 0x00}, /* H skip off, V skip off */ 697*e14d3ac8SNicholas Roth {0x5b00, 0x02}, /* OTP DPC start address */ 698*e14d3ac8SNicholas Roth {0x5b01, 0x10}, /* OTP DPC start address */ 699*e14d3ac8SNicholas Roth {0x5b02, 0x03}, /* OTP DPC end address */ 700*e14d3ac8SNicholas Roth {0x5b03, 0xcf}, /* OTP DPC end address */ 701*e14d3ac8SNicholas Roth {0x5b05, 0x6c}, /* recover method = 2b11, */ 702*e14d3ac8SNicholas Roth {0x5e00, 0x00}, /* use 0x3ff to test pattern off */ 703*e14d3ac8SNicholas Roth {0x5e01, 0x41}, /* window cut enable */ 704*e14d3ac8SNicholas Roth {0x382d, 0x7f}, 705*e14d3ac8SNicholas Roth {0x4825, 0x3a}, /* lpx_p_min */ 706*e14d3ac8SNicholas Roth {0x4826, 0x40}, /* hs_prepare_min */ 707*e14d3ac8SNicholas Roth {0x4808, 0x25}, /* wake up delay in 1/1024 s */ 708*e14d3ac8SNicholas Roth {0x3763, 0x18}, 709*e14d3ac8SNicholas Roth {0x3768, 0xcc}, 710*e14d3ac8SNicholas Roth {0x470b, 0x28}, 711*e14d3ac8SNicholas Roth {0x4202, 0x00}, 712*e14d3ac8SNicholas Roth {0x400d, 0x10}, /* BLC offset trigger L */ 713*e14d3ac8SNicholas Roth {0x4040, 0x04}, /* BLC gain th2 */ 714*e14d3ac8SNicholas Roth {0x403e, 0x04}, /* BLC gain th1 */ 715*e14d3ac8SNicholas Roth {0x4041, 0xc6}, /* BLC */ 716*e14d3ac8SNicholas Roth {0x3007, 0x80}, 717*e14d3ac8SNicholas Roth {0x400a, 0x01}, 718*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 719*e14d3ac8SNicholas Roth }; 720*e14d3ac8SNicholas Roth 721*e14d3ac8SNicholas Roth /* 722*e14d3ac8SNicholas Roth * Xclk 24Mhz 723*e14d3ac8SNicholas Roth * max_framerate 30fps 724*e14d3ac8SNicholas Roth * mipi_datarate per lane 720Mbps 725*e14d3ac8SNicholas Roth */ 726*e14d3ac8SNicholas Roth static const struct regval ov8858_1632x1224_regs_2lane[] = { 727*e14d3ac8SNicholas Roth /* 728*e14d3ac8SNicholas Roth * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz. 729*e14d3ac8SNicholas Roth * v00_01_00 (05/29/2014) : initial setting 730*e14d3ac8SNicholas Roth * AM19 : 3617 <- 0xC0 731*e14d3ac8SNicholas Roth * AM20 : change FWC_6K_EN to be default 0x3618=0x5a 732*e14d3ac8SNicholas Roth */ 733*e14d3ac8SNicholas Roth {0x0100, 0x00}, 734*e14d3ac8SNicholas Roth {0x3501, 0x4d}, /* exposure M */ 735*e14d3ac8SNicholas Roth {0x3502, 0x40}, /* exposure L */ 736*e14d3ac8SNicholas Roth {0x3778, 0x17}, 737*e14d3ac8SNicholas Roth {0x3808, 0x06}, /* x output size H */ 738*e14d3ac8SNicholas Roth {0x3809, 0x60}, /* x output size L */ 739*e14d3ac8SNicholas Roth {0x380a, 0x04}, /* y output size H */ 740*e14d3ac8SNicholas Roth {0x380b, 0xc8}, /* y output size L */ 741*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 742*e14d3ac8SNicholas Roth {0x380d, 0x88}, /* HTS L */ 743*e14d3ac8SNicholas Roth {0x380e, 0x04}, /* VTS H */ 744*e14d3ac8SNicholas Roth {0x380f, 0xdc}, /* VTS L */ 745*e14d3ac8SNicholas Roth {0x3814, 0x03}, /* x odd inc */ 746*e14d3ac8SNicholas Roth {0x3821, 0x67}, /* mirror on, bin on */ 747*e14d3ac8SNicholas Roth {0x382a, 0x03}, /* y odd inc */ 748*e14d3ac8SNicholas Roth {0x3830, 0x08}, 749*e14d3ac8SNicholas Roth {0x3836, 0x02}, 750*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 751*e14d3ac8SNicholas Roth {0x4001, 0x10}, /* total 128 black column */ 752*e14d3ac8SNicholas Roth {0x4022, 0x06}, /* Anchor left end H */ 753*e14d3ac8SNicholas Roth {0x4023, 0x00}, /* Anchor left end L */ 754*e14d3ac8SNicholas Roth {0x4025, 0x2a}, /* Anchor right start L */ 755*e14d3ac8SNicholas Roth {0x4027, 0x2b}, /* Anchor right end L */ 756*e14d3ac8SNicholas Roth {0x402b, 0x04}, /* top black line number */ 757*e14d3ac8SNicholas Roth {0x402f, 0x04}, /* bottom black line number */ 758*e14d3ac8SNicholas Roth {0x4500, 0x58}, 759*e14d3ac8SNicholas Roth {0x4600, 0x00}, 760*e14d3ac8SNicholas Roth {0x4601, 0xcb}, 761*e14d3ac8SNicholas Roth {0x382d, 0x7f}, 762*e14d3ac8SNicholas Roth {0x0100, 0x01}, 763*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 764*e14d3ac8SNicholas Roth }; 765*e14d3ac8SNicholas Roth 766*e14d3ac8SNicholas Roth /* 767*e14d3ac8SNicholas Roth * Xclk 24Mhz 768*e14d3ac8SNicholas Roth * max_framerate 15fps 769*e14d3ac8SNicholas Roth * mipi_datarate per lane 720Mbps 770*e14d3ac8SNicholas Roth */ 771*e14d3ac8SNicholas Roth static const struct regval ov8858_3264x2448_regs_2lane[] = { 772*e14d3ac8SNicholas Roth {0x0100, 0x00}, 773*e14d3ac8SNicholas Roth {0x3501, 0x9a}, /* exposure M */ 774*e14d3ac8SNicholas Roth {0x3502, 0x20}, /* exposure L */ 775*e14d3ac8SNicholas Roth {0x3778, 0x1a}, 776*e14d3ac8SNicholas Roth {0x3808, 0x0c}, /* x output size H */ 777*e14d3ac8SNicholas Roth {0x3809, 0xc0}, /* x output size L */ 778*e14d3ac8SNicholas Roth {0x380a, 0x09}, /* y output size H */ 779*e14d3ac8SNicholas Roth {0x380b, 0x90}, /* y output size L */ 780*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 781*e14d3ac8SNicholas Roth {0x380d, 0x94}, /* HTS L */ 782*e14d3ac8SNicholas Roth {0x380e, 0x09}, /* VTS H */ 783*e14d3ac8SNicholas Roth {0x380f, 0xaa}, /* VTS L */ 784*e14d3ac8SNicholas Roth {0x3814, 0x01}, /* x odd inc */ 785*e14d3ac8SNicholas Roth {0x3821, 0x46}, /* mirror on, bin off */ 786*e14d3ac8SNicholas Roth {0x382a, 0x01}, /* y odd inc */ 787*e14d3ac8SNicholas Roth {0x3830, 0x06}, 788*e14d3ac8SNicholas Roth {0x3836, 0x01}, 789*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 790*e14d3ac8SNicholas Roth {0x4001, 0x00}, /* total 256 black column */ 791*e14d3ac8SNicholas Roth {0x4022, 0x0c}, /* Anchor left end H */ 792*e14d3ac8SNicholas Roth {0x4023, 0x60}, /* Anchor left end L */ 793*e14d3ac8SNicholas Roth {0x4025, 0x36}, /* Anchor right start L */ 794*e14d3ac8SNicholas Roth {0x4027, 0x37}, /* Anchor right end L */ 795*e14d3ac8SNicholas Roth {0x402b, 0x08}, /* top black line number */ 796*e14d3ac8SNicholas Roth {0x402f, 0x08}, /* bottom black line number */ 797*e14d3ac8SNicholas Roth {0x4500, 0x58}, 798*e14d3ac8SNicholas Roth {0x4600, 0x01}, 799*e14d3ac8SNicholas Roth {0x4601, 0x97}, 800*e14d3ac8SNicholas Roth {0x382d, 0xff}, 801*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 802*e14d3ac8SNicholas Roth }; 803*e14d3ac8SNicholas Roth 804*e14d3ac8SNicholas Roth static const struct regval ov8858_global_regs_r2a_4lane[] = { 805*e14d3ac8SNicholas Roth /* 806*e14d3ac8SNicholas Roth * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz. 807*e14d3ac8SNicholas Roth * v00_01_00 (05/29/2014) : initial setting 808*e14d3ac8SNicholas Roth * AM19 : 3617 <- 0xC0 809*e14d3ac8SNicholas Roth * AM20 : change FWC_6K_EN to be default 0x3618=0x5a 810*e14d3ac8SNicholas Roth */ 811*e14d3ac8SNicholas Roth {0x0103, 0x01}, /* software reset for OVTATool only */ 812*e14d3ac8SNicholas Roth {0x0103, 0x01}, /* software reset */ 813*e14d3ac8SNicholas Roth {0x0100, 0x00}, /* software standby */ 814*e14d3ac8SNicholas Roth {0x0302, 0x1e}, /* pll1_multi */ 815*e14d3ac8SNicholas Roth {0x0303, 0x00}, /* pll1_divm */ 816*e14d3ac8SNicholas Roth {0x0304, 0x03}, /* pll1_div_mipi */ 817*e14d3ac8SNicholas Roth {0x030e, 0x00}, /* pll2_rdiv */ 818*e14d3ac8SNicholas Roth {0x030f, 0x04}, /* pll2_divsp */ 819*e14d3ac8SNicholas Roth {0x0312, 0x01}, /* pll2_pre_div0, pll2_r_divdac */ 820*e14d3ac8SNicholas Roth {0x031e, 0x0c}, /* pll1_no_lat */ 821*e14d3ac8SNicholas Roth {0x3600, 0x00}, 822*e14d3ac8SNicholas Roth {0x3601, 0x00}, 823*e14d3ac8SNicholas Roth {0x3602, 0x00}, 824*e14d3ac8SNicholas Roth {0x3603, 0x00}, 825*e14d3ac8SNicholas Roth {0x3604, 0x22}, 826*e14d3ac8SNicholas Roth {0x3605, 0x20}, 827*e14d3ac8SNicholas Roth {0x3606, 0x00}, 828*e14d3ac8SNicholas Roth {0x3607, 0x20}, 829*e14d3ac8SNicholas Roth {0x3608, 0x11}, 830*e14d3ac8SNicholas Roth {0x3609, 0x28}, 831*e14d3ac8SNicholas Roth {0x360a, 0x00}, 832*e14d3ac8SNicholas Roth {0x360b, 0x05}, 833*e14d3ac8SNicholas Roth {0x360c, 0xd4}, 834*e14d3ac8SNicholas Roth {0x360d, 0x40}, 835*e14d3ac8SNicholas Roth {0x360e, 0x0c}, 836*e14d3ac8SNicholas Roth {0x360f, 0x20}, 837*e14d3ac8SNicholas Roth {0x3610, 0x07}, 838*e14d3ac8SNicholas Roth {0x3611, 0x20}, 839*e14d3ac8SNicholas Roth {0x3612, 0x88}, 840*e14d3ac8SNicholas Roth {0x3613, 0x80}, 841*e14d3ac8SNicholas Roth {0x3614, 0x58}, 842*e14d3ac8SNicholas Roth {0x3615, 0x00}, 843*e14d3ac8SNicholas Roth {0x3616, 0x4a}, 844*e14d3ac8SNicholas Roth {0x3617, 0x90}, 845*e14d3ac8SNicholas Roth {0x3618, 0x5a}, 846*e14d3ac8SNicholas Roth {0x3619, 0x70}, 847*e14d3ac8SNicholas Roth {0x361a, 0x99}, 848*e14d3ac8SNicholas Roth {0x361b, 0x0a}, 849*e14d3ac8SNicholas Roth {0x361c, 0x07}, 850*e14d3ac8SNicholas Roth {0x361d, 0x00}, 851*e14d3ac8SNicholas Roth {0x361e, 0x00}, 852*e14d3ac8SNicholas Roth {0x361f, 0x00}, 853*e14d3ac8SNicholas Roth {0x3638, 0xff}, 854*e14d3ac8SNicholas Roth {0x3633, 0x0f}, 855*e14d3ac8SNicholas Roth {0x3634, 0x0f}, 856*e14d3ac8SNicholas Roth {0x3635, 0x0f}, 857*e14d3ac8SNicholas Roth {0x3636, 0x12}, 858*e14d3ac8SNicholas Roth {0x3645, 0x13}, 859*e14d3ac8SNicholas Roth {0x3646, 0x83}, 860*e14d3ac8SNicholas Roth {0x364a, 0x07}, 861*e14d3ac8SNicholas Roth {0x3015, 0x01}, 862*e14d3ac8SNicholas Roth {0x3018, 0x72}, /* MIPI 4 lane */ 863*e14d3ac8SNicholas Roth {0x3020, 0x93}, /* Clock switch output normal, pclk_div =/1 */ 864*e14d3ac8SNicholas Roth {0x3022, 0x01}, /* pd_mipi enable when rst_sync */ 865*e14d3ac8SNicholas Roth {0x3031, 0x0a}, /* MIPI 10-bit mode */ 866*e14d3ac8SNicholas Roth {0x3034, 0x00}, 867*e14d3ac8SNicholas Roth {0x3106, 0x01}, /* sclk_div, sclk_pre_div */ 868*e14d3ac8SNicholas Roth {0x3305, 0xf1}, 869*e14d3ac8SNicholas Roth {0x3308, 0x00}, 870*e14d3ac8SNicholas Roth {0x3309, 0x28}, 871*e14d3ac8SNicholas Roth {0x330a, 0x00}, 872*e14d3ac8SNicholas Roth {0x330b, 0x20}, 873*e14d3ac8SNicholas Roth {0x330c, 0x00}, 874*e14d3ac8SNicholas Roth {0x330d, 0x00}, 875*e14d3ac8SNicholas Roth {0x330e, 0x00}, 876*e14d3ac8SNicholas Roth {0x330f, 0x40}, 877*e14d3ac8SNicholas Roth {0x3307, 0x04}, 878*e14d3ac8SNicholas Roth {0x3500, 0x00}, /* exposure H */ 879*e14d3ac8SNicholas Roth {0x3501, 0x4d}, /* exposure M */ 880*e14d3ac8SNicholas Roth {0x3502, 0x40}, /* exposure L */ 881*e14d3ac8SNicholas Roth {0x3503, 0x80}, /* gain delay ?, exposure delay 1 frame, real gain */ 882*e14d3ac8SNicholas Roth {0x3505, 0x80}, /* gain option */ 883*e14d3ac8SNicholas Roth {0x3508, 0x02}, /* gain H */ 884*e14d3ac8SNicholas Roth {0x3509, 0x00}, /* gain L */ 885*e14d3ac8SNicholas Roth {0x350c, 0x00}, /* short gain H */ 886*e14d3ac8SNicholas Roth {0x350d, 0x80}, /* short gain L */ 887*e14d3ac8SNicholas Roth {0x3510, 0x00}, /* short exposure H */ 888*e14d3ac8SNicholas Roth {0x3511, 0x02}, /* short exposure M */ 889*e14d3ac8SNicholas Roth {0x3512, 0x00}, /* short exposure L */ 890*e14d3ac8SNicholas Roth {0x3700, 0x30}, 891*e14d3ac8SNicholas Roth {0x3701, 0x18}, 892*e14d3ac8SNicholas Roth {0x3702, 0x50}, 893*e14d3ac8SNicholas Roth {0x3703, 0x32}, 894*e14d3ac8SNicholas Roth {0x3704, 0x28}, 895*e14d3ac8SNicholas Roth {0x3705, 0x00}, 896*e14d3ac8SNicholas Roth {0x3706, 0x82}, 897*e14d3ac8SNicholas Roth {0x3707, 0x08}, 898*e14d3ac8SNicholas Roth {0x3708, 0x48}, 899*e14d3ac8SNicholas Roth {0x3709, 0x66}, 900*e14d3ac8SNicholas Roth {0x370a, 0x01}, 901*e14d3ac8SNicholas Roth {0x370b, 0x82}, 902*e14d3ac8SNicholas Roth {0x370c, 0x07}, 903*e14d3ac8SNicholas Roth {0x3718, 0x14}, 904*e14d3ac8SNicholas Roth {0x3719, 0x31}, 905*e14d3ac8SNicholas Roth {0x3712, 0x44}, 906*e14d3ac8SNicholas Roth {0x3714, 0x24}, 907*e14d3ac8SNicholas Roth {0x371e, 0x31}, 908*e14d3ac8SNicholas Roth {0x371f, 0x7f}, 909*e14d3ac8SNicholas Roth {0x3720, 0x0a}, 910*e14d3ac8SNicholas Roth {0x3721, 0x0a}, 911*e14d3ac8SNicholas Roth {0x3724, 0x0c}, 912*e14d3ac8SNicholas Roth {0x3725, 0x02}, 913*e14d3ac8SNicholas Roth {0x3726, 0x0c}, 914*e14d3ac8SNicholas Roth {0x3728, 0x0a}, 915*e14d3ac8SNicholas Roth {0x3729, 0x03}, 916*e14d3ac8SNicholas Roth {0x372a, 0x06}, 917*e14d3ac8SNicholas Roth {0x372b, 0xa6}, 918*e14d3ac8SNicholas Roth {0x372c, 0xa6}, 919*e14d3ac8SNicholas Roth {0x372d, 0xa6}, 920*e14d3ac8SNicholas Roth {0x372e, 0x0c}, 921*e14d3ac8SNicholas Roth {0x372f, 0x20}, 922*e14d3ac8SNicholas Roth {0x3730, 0x02}, 923*e14d3ac8SNicholas Roth {0x3731, 0x0c}, 924*e14d3ac8SNicholas Roth {0x3732, 0x28}, 925*e14d3ac8SNicholas Roth {0x3733, 0x10}, 926*e14d3ac8SNicholas Roth {0x3734, 0x40}, 927*e14d3ac8SNicholas Roth {0x3736, 0x30}, 928*e14d3ac8SNicholas Roth {0x373a, 0x0a}, 929*e14d3ac8SNicholas Roth {0x373b, 0x0b}, 930*e14d3ac8SNicholas Roth {0x373c, 0x14}, 931*e14d3ac8SNicholas Roth {0x373e, 0x06}, 932*e14d3ac8SNicholas Roth {0x3750, 0x0a}, 933*e14d3ac8SNicholas Roth {0x3751, 0x0e}, 934*e14d3ac8SNicholas Roth {0x3755, 0x10}, 935*e14d3ac8SNicholas Roth {0x3758, 0x00}, 936*e14d3ac8SNicholas Roth {0x3759, 0x4c}, 937*e14d3ac8SNicholas Roth {0x375a, 0x0c}, 938*e14d3ac8SNicholas Roth {0x375b, 0x26}, 939*e14d3ac8SNicholas Roth {0x375c, 0x20}, 940*e14d3ac8SNicholas Roth {0x375d, 0x04}, 941*e14d3ac8SNicholas Roth {0x375e, 0x00}, 942*e14d3ac8SNicholas Roth {0x375f, 0x28}, 943*e14d3ac8SNicholas Roth {0x3768, 0x22}, 944*e14d3ac8SNicholas Roth {0x3769, 0x44}, 945*e14d3ac8SNicholas Roth {0x376a, 0x44}, 946*e14d3ac8SNicholas Roth {0x3761, 0x00}, 947*e14d3ac8SNicholas Roth {0x3762, 0x00}, 948*e14d3ac8SNicholas Roth {0x3763, 0x00}, 949*e14d3ac8SNicholas Roth {0x3766, 0xff}, 950*e14d3ac8SNicholas Roth {0x376b, 0x00}, 951*e14d3ac8SNicholas Roth {0x3772, 0x46}, 952*e14d3ac8SNicholas Roth {0x3773, 0x04}, 953*e14d3ac8SNicholas Roth {0x3774, 0x2c}, 954*e14d3ac8SNicholas Roth {0x3775, 0x13}, 955*e14d3ac8SNicholas Roth {0x3776, 0x08}, 956*e14d3ac8SNicholas Roth {0x3777, 0x00}, 957*e14d3ac8SNicholas Roth {0x3778, 0x17}, 958*e14d3ac8SNicholas Roth {0x37a0, 0x88}, 959*e14d3ac8SNicholas Roth {0x37a1, 0x7a}, 960*e14d3ac8SNicholas Roth {0x37a2, 0x7a}, 961*e14d3ac8SNicholas Roth {0x37a3, 0x00}, 962*e14d3ac8SNicholas Roth {0x37a4, 0x00}, 963*e14d3ac8SNicholas Roth {0x37a5, 0x00}, 964*e14d3ac8SNicholas Roth {0x37a6, 0x00}, 965*e14d3ac8SNicholas Roth {0x37a7, 0x88}, 966*e14d3ac8SNicholas Roth {0x37a8, 0x98}, 967*e14d3ac8SNicholas Roth {0x37a9, 0x98}, 968*e14d3ac8SNicholas Roth {0x3760, 0x00}, 969*e14d3ac8SNicholas Roth {0x376f, 0x01}, 970*e14d3ac8SNicholas Roth {0x37aa, 0x88}, 971*e14d3ac8SNicholas Roth {0x37ab, 0x5c}, 972*e14d3ac8SNicholas Roth {0x37ac, 0x5c}, 973*e14d3ac8SNicholas Roth {0x37ad, 0x55}, 974*e14d3ac8SNicholas Roth {0x37ae, 0x19}, 975*e14d3ac8SNicholas Roth {0x37af, 0x19}, 976*e14d3ac8SNicholas Roth {0x37b0, 0x00}, 977*e14d3ac8SNicholas Roth {0x37b1, 0x00}, 978*e14d3ac8SNicholas Roth {0x37b2, 0x00}, 979*e14d3ac8SNicholas Roth {0x37b3, 0x84}, 980*e14d3ac8SNicholas Roth {0x37b4, 0x84}, 981*e14d3ac8SNicholas Roth {0x37b5, 0x60}, 982*e14d3ac8SNicholas Roth {0x37b6, 0x00}, 983*e14d3ac8SNicholas Roth {0x37b7, 0x00}, 984*e14d3ac8SNicholas Roth {0x37b8, 0x00}, 985*e14d3ac8SNicholas Roth {0x37b9, 0xff}, 986*e14d3ac8SNicholas Roth {0x3800, 0x00}, /* x start H */ 987*e14d3ac8SNicholas Roth {0x3801, 0x0c}, /* x start L */ 988*e14d3ac8SNicholas Roth {0x3802, 0x00}, /* y start H */ 989*e14d3ac8SNicholas Roth {0x3803, 0x0c}, /* y start L */ 990*e14d3ac8SNicholas Roth {0x3804, 0x0c}, /* x end H */ 991*e14d3ac8SNicholas Roth {0x3805, 0xd3}, /* x end L */ 992*e14d3ac8SNicholas Roth {0x3806, 0x09}, /* y end H */ 993*e14d3ac8SNicholas Roth {0x3807, 0xa3}, /* y end L */ 994*e14d3ac8SNicholas Roth {0x3808, 0x06}, /* x output size H */ 995*e14d3ac8SNicholas Roth {0x3809, 0x60}, /* x output size L */ 996*e14d3ac8SNicholas Roth {0x380a, 0x04}, /* y output size H */ 997*e14d3ac8SNicholas Roth {0x380b, 0xc8}, /* y output size L */ 998*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 999*e14d3ac8SNicholas Roth {0x380d, 0x88}, /* HTS L */ 1000*e14d3ac8SNicholas Roth {0x380e, 0x04}, /* VTS H */ 1001*e14d3ac8SNicholas Roth {0x380f, 0xdc}, /* VTS L */ 1002*e14d3ac8SNicholas Roth {0x3810, 0x00}, /* ISP x win H */ 1003*e14d3ac8SNicholas Roth {0x3811, 0x04}, /* ISP x win L */ 1004*e14d3ac8SNicholas Roth {0x3813, 0x02}, /* ISP y win L */ 1005*e14d3ac8SNicholas Roth {0x3814, 0x03}, /* x odd inc */ 1006*e14d3ac8SNicholas Roth {0x3815, 0x01}, /* x even inc */ 1007*e14d3ac8SNicholas Roth {0x3820, 0x00}, /* vflip off */ 1008*e14d3ac8SNicholas Roth {0x3821, 0x67}, /* mirror on, bin o */ 1009*e14d3ac8SNicholas Roth {0x382a, 0x03}, /* y odd inc */ 1010*e14d3ac8SNicholas Roth {0x382b, 0x01}, /* y even inc */ 1011*e14d3ac8SNicholas Roth {0x3830, 0x08}, 1012*e14d3ac8SNicholas Roth {0x3836, 0x02}, 1013*e14d3ac8SNicholas Roth {0x3837, 0x18}, 1014*e14d3ac8SNicholas Roth {0x3841, 0xff}, /* window auto size enable */ 1015*e14d3ac8SNicholas Roth {0x3846, 0x48}, 1016*e14d3ac8SNicholas Roth {0x3d85, 0x16}, /* OTP power up load data/setting enable */ 1017*e14d3ac8SNicholas Roth {0x3d8c, 0x73}, /* OTP setting start High */ 1018*e14d3ac8SNicholas Roth {0x3d8d, 0xde}, /* OTP setting start Low */ 1019*e14d3ac8SNicholas Roth {0x3f08, 0x10}, 1020*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 1021*e14d3ac8SNicholas Roth {0x4000, 0xf1}, /* out_range/format_chg/gain/exp_chg trig enable */ 1022*e14d3ac8SNicholas Roth {0x4001, 0x10}, /* total 128 black column */ 1023*e14d3ac8SNicholas Roth {0x4005, 0x10}, /* BLC target L */ 1024*e14d3ac8SNicholas Roth {0x4002, 0x27}, /* value used to limit BLC offset */ 1025*e14d3ac8SNicholas Roth {0x4009, 0x81}, /* final BLC offset limitation enable */ 1026*e14d3ac8SNicholas Roth {0x400b, 0x0c}, /* DCBLC on, DCBLC manual mode on */ 1027*e14d3ac8SNicholas Roth {0x401b, 0x00}, /* zero line R coefficient */ 1028*e14d3ac8SNicholas Roth {0x401d, 0x00}, /* zoro line T coefficient */ 1029*e14d3ac8SNicholas Roth {0x4020, 0x00}, /* Anchor left start H */ 1030*e14d3ac8SNicholas Roth {0x4021, 0x04}, /* Anchor left start L */ 1031*e14d3ac8SNicholas Roth {0x4022, 0x06}, /* Anchor left end H */ 1032*e14d3ac8SNicholas Roth {0x4023, 0x00}, /* Anchor left end L */ 1033*e14d3ac8SNicholas Roth {0x4024, 0x0f}, /* Anchor right start H */ 1034*e14d3ac8SNicholas Roth {0x4025, 0x2a}, /* Anchor right start L */ 1035*e14d3ac8SNicholas Roth {0x4026, 0x0f}, /* Anchor right end H */ 1036*e14d3ac8SNicholas Roth {0x4027, 0x2b}, /* Anchor right end L */ 1037*e14d3ac8SNicholas Roth {0x4028, 0x00}, /* top zero line start */ 1038*e14d3ac8SNicholas Roth {0x4029, 0x02}, /* top zero line number */ 1039*e14d3ac8SNicholas Roth {0x402a, 0x04}, /* top black line start */ 1040*e14d3ac8SNicholas Roth {0x402b, 0x04}, /* top black line number */ 1041*e14d3ac8SNicholas Roth {0x402c, 0x00}, /* bottom zero line start */ 1042*e14d3ac8SNicholas Roth {0x402d, 0x02}, /* bottom zoro line number */ 1043*e14d3ac8SNicholas Roth {0x402e, 0x04}, /* bottom black line start */ 1044*e14d3ac8SNicholas Roth {0x402f, 0x04}, /* bottom black line number */ 1045*e14d3ac8SNicholas Roth {0x401f, 0x00}, /* interpolation x/y disable, Anchor one disable */ 1046*e14d3ac8SNicholas Roth {0x4034, 0x3f}, 1047*e14d3ac8SNicholas Roth {0x403d, 0x04}, /* md_precision_en */ 1048*e14d3ac8SNicholas Roth {0x4300, 0xff}, /* clip max H */ 1049*e14d3ac8SNicholas Roth {0x4301, 0x00}, /* clip min H */ 1050*e14d3ac8SNicholas Roth {0x4302, 0x0f}, /* clip min L, clip max L */ 1051*e14d3ac8SNicholas Roth {0x4316, 0x00}, 1052*e14d3ac8SNicholas Roth {0x4500, 0x58}, 1053*e14d3ac8SNicholas Roth {0x4503, 0x18}, 1054*e14d3ac8SNicholas Roth {0x4600, 0x00}, 1055*e14d3ac8SNicholas Roth {0x4601, 0xcb}, 1056*e14d3ac8SNicholas Roth {0x481f, 0x32}, /* clk prepare min */ 1057*e14d3ac8SNicholas Roth {0x4837, 0x16}, /* global timing */ 1058*e14d3ac8SNicholas Roth {0x4850, 0x10}, /* lane 1 = 1, lane 0 = 0 */ 1059*e14d3ac8SNicholas Roth {0x4851, 0x32}, /* lane 3 = 3, lane 2 = 2 */ 1060*e14d3ac8SNicholas Roth {0x4b00, 0x2a}, 1061*e14d3ac8SNicholas Roth {0x4b0d, 0x00}, 1062*e14d3ac8SNicholas Roth {0x4d00, 0x04}, /* temperature sensor */ 1063*e14d3ac8SNicholas Roth {0x4d01, 0x18}, 1064*e14d3ac8SNicholas Roth {0x4d02, 0xc3}, 1065*e14d3ac8SNicholas Roth {0x4d03, 0xff}, 1066*e14d3ac8SNicholas Roth {0x4d04, 0xff}, 1067*e14d3ac8SNicholas Roth {0x4d05, 0xff}, /* temperature sensor */ 1068*e14d3ac8SNicholas Roth {0x5000, 0xfe}, /* lenc on, slave/master AWB gain/statistics enable */ 1069*e14d3ac8SNicholas Roth {0x5001, 0x01}, /* BLC on */ 1070*e14d3ac8SNicholas Roth {0x5002, 0x08}, /* WBMATCH sensor's gain, H scale/WBMATCH/OTP_DPC off */ 1071*e14d3ac8SNicholas Roth {0x5003, 0x20}, /* DPC_DBC buffer control enable, WB */ 1072*e14d3ac8SNicholas Roth {0x501e, 0x93}, /* enable digital gain */ 1073*e14d3ac8SNicholas Roth {0x5046, 0x12}, 1074*e14d3ac8SNicholas Roth {0x5780, 0x3e}, /* DPC */ 1075*e14d3ac8SNicholas Roth {0x5781, 0x0f}, 1076*e14d3ac8SNicholas Roth {0x5782, 0x44}, 1077*e14d3ac8SNicholas Roth {0x5783, 0x02}, 1078*e14d3ac8SNicholas Roth {0x5784, 0x01}, 1079*e14d3ac8SNicholas Roth {0x5785, 0x00}, 1080*e14d3ac8SNicholas Roth {0x5786, 0x00}, 1081*e14d3ac8SNicholas Roth {0x5787, 0x04}, 1082*e14d3ac8SNicholas Roth {0x5788, 0x02}, 1083*e14d3ac8SNicholas Roth {0x5789, 0x0f}, 1084*e14d3ac8SNicholas Roth {0x578a, 0xfd}, 1085*e14d3ac8SNicholas Roth {0x578b, 0xf5}, 1086*e14d3ac8SNicholas Roth {0x578c, 0xf5}, 1087*e14d3ac8SNicholas Roth {0x578d, 0x03}, 1088*e14d3ac8SNicholas Roth {0x578e, 0x08}, 1089*e14d3ac8SNicholas Roth {0x578f, 0x0c}, 1090*e14d3ac8SNicholas Roth {0x5790, 0x08}, 1091*e14d3ac8SNicholas Roth {0x5791, 0x04}, 1092*e14d3ac8SNicholas Roth {0x5792, 0x00}, 1093*e14d3ac8SNicholas Roth {0x5793, 0x52}, 1094*e14d3ac8SNicholas Roth {0x5794, 0xa3}, /* DPC */ 1095*e14d3ac8SNicholas Roth {0x5871, 0x0d}, /* Lenc */ 1096*e14d3ac8SNicholas Roth {0x5870, 0x18}, 1097*e14d3ac8SNicholas Roth {0x586e, 0x10}, 1098*e14d3ac8SNicholas Roth {0x586f, 0x08}, 1099*e14d3ac8SNicholas Roth {0x58f7, 0x01}, 1100*e14d3ac8SNicholas Roth {0x58f8, 0x3d}, /* Lenc */ 1101*e14d3ac8SNicholas Roth {0x5901, 0x00}, /* H skip off, V skip off */ 1102*e14d3ac8SNicholas Roth {0x5b00, 0x02}, /* OTP DPC start address */ 1103*e14d3ac8SNicholas Roth {0x5b01, 0x10}, /* OTP DPC start address */ 1104*e14d3ac8SNicholas Roth {0x5b02, 0x03}, /* OTP DPC end address */ 1105*e14d3ac8SNicholas Roth {0x5b03, 0xcf}, /* OTP DPC end address */ 1106*e14d3ac8SNicholas Roth {0x5b05, 0x6c}, /* recover method = 2b11 */ 1107*e14d3ac8SNicholas Roth {0x5e00, 0x00}, /* use 0x3ff to test pattern off */ 1108*e14d3ac8SNicholas Roth {0x5e01, 0x41}, /* window cut enable */ 1109*e14d3ac8SNicholas Roth {0x382d, 0x7f}, 1110*e14d3ac8SNicholas Roth {0x4825, 0x3a}, /* lpx_p_min */ 1111*e14d3ac8SNicholas Roth {0x4826, 0x40}, /* hs_prepare_min */ 1112*e14d3ac8SNicholas Roth {0x4808, 0x25}, /* wake up delay in 1/1024 s */ 1113*e14d3ac8SNicholas Roth {0x3763, 0x18}, 1114*e14d3ac8SNicholas Roth {0x3768, 0xcc}, 1115*e14d3ac8SNicholas Roth {0x470b, 0x28}, 1116*e14d3ac8SNicholas Roth {0x4202, 0x00}, 1117*e14d3ac8SNicholas Roth {0x400d, 0x10}, /* BLC offset trigger L */ 1118*e14d3ac8SNicholas Roth {0x4040, 0x04}, /* BLC gain th2 */ 1119*e14d3ac8SNicholas Roth {0x403e, 0x04}, /* BLC gain th1 */ 1120*e14d3ac8SNicholas Roth {0x4041, 0xc6}, /* BLC */ 1121*e14d3ac8SNicholas Roth {0x3007, 0x80}, 1122*e14d3ac8SNicholas Roth {0x400a, 0x01}, 1123*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 1124*e14d3ac8SNicholas Roth }; 1125*e14d3ac8SNicholas Roth 1126*e14d3ac8SNicholas Roth /* 1127*e14d3ac8SNicholas Roth * Xclk 24Mhz 1128*e14d3ac8SNicholas Roth * max_framerate 60fps 1129*e14d3ac8SNicholas Roth * mipi_datarate per lane 720Mbps 1130*e14d3ac8SNicholas Roth */ 1131*e14d3ac8SNicholas Roth static const struct regval ov8858_1632x1224_regs_4lane[] = { 1132*e14d3ac8SNicholas Roth {0x0100, 0x00}, 1133*e14d3ac8SNicholas Roth {0x3501, 0x4d}, /* exposure M */ 1134*e14d3ac8SNicholas Roth {0x3502, 0x40}, /* exposure L */ 1135*e14d3ac8SNicholas Roth {0x3808, 0x06}, /* x output size H */ 1136*e14d3ac8SNicholas Roth {0x3809, 0x60}, /* x output size L */ 1137*e14d3ac8SNicholas Roth {0x380a, 0x04}, /* y output size H */ 1138*e14d3ac8SNicholas Roth {0x380b, 0xc8}, /* y output size L */ 1139*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 1140*e14d3ac8SNicholas Roth {0x380d, 0x88}, /* HTS L */ 1141*e14d3ac8SNicholas Roth {0x380e, 0x04}, /* VTS H */ 1142*e14d3ac8SNicholas Roth {0x380f, 0xdc}, /* VTS L */ 1143*e14d3ac8SNicholas Roth {0x3814, 0x03}, /* x odd inc */ 1144*e14d3ac8SNicholas Roth {0x3821, 0x67}, /* mirror on, bin on */ 1145*e14d3ac8SNicholas Roth {0x382a, 0x03}, /* y odd inc */ 1146*e14d3ac8SNicholas Roth {0x3830, 0x08}, 1147*e14d3ac8SNicholas Roth {0x3836, 0x02}, 1148*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 1149*e14d3ac8SNicholas Roth {0x4001, 0x10}, /* total 128 black column */ 1150*e14d3ac8SNicholas Roth {0x4022, 0x06}, /* Anchor left end H */ 1151*e14d3ac8SNicholas Roth {0x4023, 0x00}, /* Anchor left end L */ 1152*e14d3ac8SNicholas Roth {0x4025, 0x2a}, /* Anchor right start L */ 1153*e14d3ac8SNicholas Roth {0x4027, 0x2b}, /* Anchor right end L */ 1154*e14d3ac8SNicholas Roth {0x402b, 0x04}, /* top black line number */ 1155*e14d3ac8SNicholas Roth {0x402f, 0x04}, /* bottom black line number */ 1156*e14d3ac8SNicholas Roth {0x4500, 0x58}, 1157*e14d3ac8SNicholas Roth {0x4600, 0x00}, 1158*e14d3ac8SNicholas Roth {0x4601, 0xcb}, 1159*e14d3ac8SNicholas Roth {0x382d, 0x7f}, 1160*e14d3ac8SNicholas Roth {0x0100, 0x01}, 1161*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 1162*e14d3ac8SNicholas Roth }; 1163*e14d3ac8SNicholas Roth 1164*e14d3ac8SNicholas Roth /* 1165*e14d3ac8SNicholas Roth * Xclk 24Mhz 1166*e14d3ac8SNicholas Roth * max_framerate 30fps 1167*e14d3ac8SNicholas Roth * mipi_datarate per lane 720Mbps 1168*e14d3ac8SNicholas Roth */ 1169*e14d3ac8SNicholas Roth static const struct regval ov8858_3264x2448_regs_4lane[] = { 1170*e14d3ac8SNicholas Roth {0x0100, 0x00}, 1171*e14d3ac8SNicholas Roth {0x3501, 0x9a}, /* exposure M */ 1172*e14d3ac8SNicholas Roth {0x3502, 0x20}, /* exposure L */ 1173*e14d3ac8SNicholas Roth {0x3808, 0x0c}, /* x output size H */ 1174*e14d3ac8SNicholas Roth {0x3809, 0xc0}, /* x output size L */ 1175*e14d3ac8SNicholas Roth {0x380a, 0x09}, /* y output size H */ 1176*e14d3ac8SNicholas Roth {0x380b, 0x90}, /* y output size L */ 1177*e14d3ac8SNicholas Roth {0x380c, 0x07}, /* HTS H */ 1178*e14d3ac8SNicholas Roth {0x380d, 0x94}, /* HTS L */ 1179*e14d3ac8SNicholas Roth {0x380e, 0x09}, /* VTS H */ 1180*e14d3ac8SNicholas Roth {0x380f, 0xaa}, /* VTS L */ 1181*e14d3ac8SNicholas Roth {0x3814, 0x01}, /* x odd inc */ 1182*e14d3ac8SNicholas Roth {0x3821, 0x46}, /* mirror on, bin off */ 1183*e14d3ac8SNicholas Roth {0x382a, 0x01}, /* y odd inc */ 1184*e14d3ac8SNicholas Roth {0x3830, 0x06}, 1185*e14d3ac8SNicholas Roth {0x3836, 0x01}, 1186*e14d3ac8SNicholas Roth {0x3f0a, 0x00}, 1187*e14d3ac8SNicholas Roth {0x4001, 0x00}, /* total 256 black column */ 1188*e14d3ac8SNicholas Roth {0x4022, 0x0c}, /* Anchor left end H */ 1189*e14d3ac8SNicholas Roth {0x4023, 0x60}, /* Anchor left end L */ 1190*e14d3ac8SNicholas Roth {0x4025, 0x36}, /* Anchor right start L */ 1191*e14d3ac8SNicholas Roth {0x4027, 0x37}, /* Anchor right end L */ 1192*e14d3ac8SNicholas Roth {0x402b, 0x08}, /* top black line number */ 1193*e14d3ac8SNicholas Roth {0x402f, 0x08}, /* interpolation x/y disable, Anchor one disable */ 1194*e14d3ac8SNicholas Roth {0x4500, 0x58}, 1195*e14d3ac8SNicholas Roth {0x4600, 0x01}, 1196*e14d3ac8SNicholas Roth {0x4601, 0x97}, 1197*e14d3ac8SNicholas Roth {0x382d, 0xff}, 1198*e14d3ac8SNicholas Roth {REG_NULL, 0x00}, 1199*e14d3ac8SNicholas Roth }; 1200*e14d3ac8SNicholas Roth 1201*e14d3ac8SNicholas Roth static const struct ov8858_mode ov8858_modes[] = { 1202*e14d3ac8SNicholas Roth { 1203*e14d3ac8SNicholas Roth .width = 3264, 1204*e14d3ac8SNicholas Roth .height = 2448, 1205*e14d3ac8SNicholas Roth .exp_def = 2464, 1206*e14d3ac8SNicholas Roth .hts_def = 1940 * 2, 1207*e14d3ac8SNicholas Roth .vts_def = 2472, 1208*e14d3ac8SNicholas Roth .reg_modes = { 1209*e14d3ac8SNicholas Roth .mode_2lanes = ov8858_3264x2448_regs_2lane, 1210*e14d3ac8SNicholas Roth .mode_4lanes = ov8858_3264x2448_regs_4lane, 1211*e14d3ac8SNicholas Roth }, 1212*e14d3ac8SNicholas Roth }, 1213*e14d3ac8SNicholas Roth { 1214*e14d3ac8SNicholas Roth .width = 1632, 1215*e14d3ac8SNicholas Roth .height = 1224, 1216*e14d3ac8SNicholas Roth .exp_def = 1232, 1217*e14d3ac8SNicholas Roth .hts_def = 1928 * 2, 1218*e14d3ac8SNicholas Roth .vts_def = 1244, 1219*e14d3ac8SNicholas Roth .reg_modes = { 1220*e14d3ac8SNicholas Roth .mode_2lanes = ov8858_1632x1224_regs_2lane, 1221*e14d3ac8SNicholas Roth .mode_4lanes = ov8858_1632x1224_regs_4lane, 1222*e14d3ac8SNicholas Roth }, 1223*e14d3ac8SNicholas Roth }, 1224*e14d3ac8SNicholas Roth }; 1225*e14d3ac8SNicholas Roth 1226*e14d3ac8SNicholas Roth static const s64 link_freq_menu_items[] = { 1227*e14d3ac8SNicholas Roth OV8858_LINK_FREQ 1228*e14d3ac8SNicholas Roth }; 1229*e14d3ac8SNicholas Roth 1230*e14d3ac8SNicholas Roth static const char * const ov8858_test_pattern_menu[] = { 1231*e14d3ac8SNicholas Roth "Disabled", 1232*e14d3ac8SNicholas Roth "Vertical Color Bar Type 1", 1233*e14d3ac8SNicholas Roth "Vertical Color Bar Type 2", 1234*e14d3ac8SNicholas Roth "Vertical Color Bar Type 3", 1235*e14d3ac8SNicholas Roth "Vertical Color Bar Type 4" 1236*e14d3ac8SNicholas Roth }; 1237*e14d3ac8SNicholas Roth 1238*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1239*e14d3ac8SNicholas Roth * HW access 1240*e14d3ac8SNicholas Roth */ 1241*e14d3ac8SNicholas Roth 1242*e14d3ac8SNicholas Roth static int ov8858_write(struct ov8858 *ov8858, u32 reg, u32 val, int *err) 1243*e14d3ac8SNicholas Roth { 1244*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1245*e14d3ac8SNicholas Roth unsigned int len = (reg >> OV8858_REG_SIZE_SHIFT) & 3; 1246*e14d3ac8SNicholas Roth u16 addr = reg & OV8858_REG_ADDR_MASK; 1247*e14d3ac8SNicholas Roth u8 buf[6]; 1248*e14d3ac8SNicholas Roth int ret; 1249*e14d3ac8SNicholas Roth 1250*e14d3ac8SNicholas Roth if (err && *err) 1251*e14d3ac8SNicholas Roth return *err; 1252*e14d3ac8SNicholas Roth 1253*e14d3ac8SNicholas Roth put_unaligned_be16(addr, buf); 1254*e14d3ac8SNicholas Roth put_unaligned_be32(val << (8 * (4 - len)), buf + 2); 1255*e14d3ac8SNicholas Roth 1256*e14d3ac8SNicholas Roth ret = i2c_master_send(client, buf, len + 2); 1257*e14d3ac8SNicholas Roth if (ret != len + 2) { 1258*e14d3ac8SNicholas Roth ret = ret < 0 ? ret : -EIO; 1259*e14d3ac8SNicholas Roth if (err) 1260*e14d3ac8SNicholas Roth *err = ret; 1261*e14d3ac8SNicholas Roth 1262*e14d3ac8SNicholas Roth dev_err(&client->dev, 1263*e14d3ac8SNicholas Roth "Failed to write reg %u: %d\n", addr, ret); 1264*e14d3ac8SNicholas Roth return ret; 1265*e14d3ac8SNicholas Roth } 1266*e14d3ac8SNicholas Roth 1267*e14d3ac8SNicholas Roth return 0; 1268*e14d3ac8SNicholas Roth } 1269*e14d3ac8SNicholas Roth 1270*e14d3ac8SNicholas Roth static int ov8858_write_array(struct ov8858 *ov8858, const struct regval *regs) 1271*e14d3ac8SNicholas Roth { 1272*e14d3ac8SNicholas Roth unsigned int i; 1273*e14d3ac8SNicholas Roth int ret = 0; 1274*e14d3ac8SNicholas Roth 1275*e14d3ac8SNicholas Roth for (i = 0; ret == 0 && regs[i].addr != REG_NULL; ++i) { 1276*e14d3ac8SNicholas Roth ov8858_write(ov8858, OV8858_REG_8BIT(regs[i].addr), 1277*e14d3ac8SNicholas Roth regs[i].val, &ret); 1278*e14d3ac8SNicholas Roth } 1279*e14d3ac8SNicholas Roth 1280*e14d3ac8SNicholas Roth return ret; 1281*e14d3ac8SNicholas Roth } 1282*e14d3ac8SNicholas Roth 1283*e14d3ac8SNicholas Roth static int ov8858_read(struct ov8858 *ov8858, u32 reg, u32 *val) 1284*e14d3ac8SNicholas Roth { 1285*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1286*e14d3ac8SNicholas Roth __be16 reg_addr_be = cpu_to_be16(reg & OV8858_REG_ADDR_MASK); 1287*e14d3ac8SNicholas Roth unsigned int len = (reg >> OV8858_REG_SIZE_SHIFT) & 3; 1288*e14d3ac8SNicholas Roth struct i2c_msg msgs[2]; 1289*e14d3ac8SNicholas Roth __be32 data_be = 0; 1290*e14d3ac8SNicholas Roth u8 *data_be_p; 1291*e14d3ac8SNicholas Roth int ret; 1292*e14d3ac8SNicholas Roth 1293*e14d3ac8SNicholas Roth data_be_p = (u8 *)&data_be; 1294*e14d3ac8SNicholas Roth 1295*e14d3ac8SNicholas Roth /* Write register address */ 1296*e14d3ac8SNicholas Roth msgs[0].addr = client->addr; 1297*e14d3ac8SNicholas Roth msgs[0].flags = 0; 1298*e14d3ac8SNicholas Roth msgs[0].len = 2; 1299*e14d3ac8SNicholas Roth msgs[0].buf = (u8 *)®_addr_be; 1300*e14d3ac8SNicholas Roth 1301*e14d3ac8SNicholas Roth /* Read data from register */ 1302*e14d3ac8SNicholas Roth msgs[1].addr = client->addr; 1303*e14d3ac8SNicholas Roth msgs[1].flags = I2C_M_RD; 1304*e14d3ac8SNicholas Roth msgs[1].len = len; 1305*e14d3ac8SNicholas Roth msgs[1].buf = &data_be_p[4 - len]; 1306*e14d3ac8SNicholas Roth 1307*e14d3ac8SNicholas Roth ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 1308*e14d3ac8SNicholas Roth if (ret != ARRAY_SIZE(msgs)) { 1309*e14d3ac8SNicholas Roth ret = ret < 0 ? ret : -EIO; 1310*e14d3ac8SNicholas Roth dev_err(&client->dev, 1311*e14d3ac8SNicholas Roth "Failed to read reg %u: %d\n", reg, ret); 1312*e14d3ac8SNicholas Roth return ret; 1313*e14d3ac8SNicholas Roth } 1314*e14d3ac8SNicholas Roth 1315*e14d3ac8SNicholas Roth *val = be32_to_cpu(data_be); 1316*e14d3ac8SNicholas Roth 1317*e14d3ac8SNicholas Roth return 0; 1318*e14d3ac8SNicholas Roth } 1319*e14d3ac8SNicholas Roth 1320*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1321*e14d3ac8SNicholas Roth * Streaming 1322*e14d3ac8SNicholas Roth */ 1323*e14d3ac8SNicholas Roth 1324*e14d3ac8SNicholas Roth static int ov8858_start_stream(struct ov8858 *ov8858, 1325*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state) 1326*e14d3ac8SNicholas Roth { 1327*e14d3ac8SNicholas Roth struct v4l2_mbus_framefmt *format; 1328*e14d3ac8SNicholas Roth const struct ov8858_mode *mode; 1329*e14d3ac8SNicholas Roth const struct regval *reg_list; 1330*e14d3ac8SNicholas Roth int ret; 1331*e14d3ac8SNicholas Roth 1332*e14d3ac8SNicholas Roth ret = ov8858_write_array(ov8858, ov8858->global_regs); 1333*e14d3ac8SNicholas Roth if (ret) 1334*e14d3ac8SNicholas Roth return ret; 1335*e14d3ac8SNicholas Roth 1336*e14d3ac8SNicholas Roth format = v4l2_subdev_get_pad_format(&ov8858->subdev, state, 0); 1337*e14d3ac8SNicholas Roth mode = v4l2_find_nearest_size(ov8858_modes, ARRAY_SIZE(ov8858_modes), 1338*e14d3ac8SNicholas Roth width, height, format->width, 1339*e14d3ac8SNicholas Roth format->height); 1340*e14d3ac8SNicholas Roth 1341*e14d3ac8SNicholas Roth reg_list = ov8858->num_lanes == 4 1342*e14d3ac8SNicholas Roth ? mode->reg_modes.mode_4lanes 1343*e14d3ac8SNicholas Roth : mode->reg_modes.mode_2lanes; 1344*e14d3ac8SNicholas Roth 1345*e14d3ac8SNicholas Roth ret = ov8858_write_array(ov8858, reg_list); 1346*e14d3ac8SNicholas Roth if (ret) 1347*e14d3ac8SNicholas Roth return ret; 1348*e14d3ac8SNicholas Roth 1349*e14d3ac8SNicholas Roth /* 200 usec max to let PLL stabilize. */ 1350*e14d3ac8SNicholas Roth fsleep(200); 1351*e14d3ac8SNicholas Roth 1352*e14d3ac8SNicholas Roth ret = __v4l2_ctrl_handler_setup(&ov8858->ctrl_handler); 1353*e14d3ac8SNicholas Roth if (ret) 1354*e14d3ac8SNicholas Roth return ret; 1355*e14d3ac8SNicholas Roth 1356*e14d3ac8SNicholas Roth ret = ov8858_write(ov8858, OV8858_REG_SC_CTRL0100, 1357*e14d3ac8SNicholas Roth OV8858_MODE_STREAMING, NULL); 1358*e14d3ac8SNicholas Roth if (ret) 1359*e14d3ac8SNicholas Roth return ret; 1360*e14d3ac8SNicholas Roth 1361*e14d3ac8SNicholas Roth /* t5 (fixed) = 10msec before entering streaming state */ 1362*e14d3ac8SNicholas Roth fsleep(10000); 1363*e14d3ac8SNicholas Roth 1364*e14d3ac8SNicholas Roth return 0; 1365*e14d3ac8SNicholas Roth } 1366*e14d3ac8SNicholas Roth 1367*e14d3ac8SNicholas Roth static int ov8858_stop_stream(struct ov8858 *ov8858) 1368*e14d3ac8SNicholas Roth { 1369*e14d3ac8SNicholas Roth return ov8858_write(ov8858, OV8858_REG_SC_CTRL0100, 1370*e14d3ac8SNicholas Roth OV8858_MODE_SW_STANDBY, NULL); 1371*e14d3ac8SNicholas Roth } 1372*e14d3ac8SNicholas Roth 1373*e14d3ac8SNicholas Roth static int ov8858_s_stream(struct v4l2_subdev *sd, int on) 1374*e14d3ac8SNicholas Roth { 1375*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(sd); 1376*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = sd_to_ov8858(sd); 1377*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state; 1378*e14d3ac8SNicholas Roth int ret = 0; 1379*e14d3ac8SNicholas Roth 1380*e14d3ac8SNicholas Roth state = v4l2_subdev_lock_and_get_active_state(sd); 1381*e14d3ac8SNicholas Roth 1382*e14d3ac8SNicholas Roth if (on) { 1383*e14d3ac8SNicholas Roth ret = pm_runtime_resume_and_get(&client->dev); 1384*e14d3ac8SNicholas Roth if (ret < 0) 1385*e14d3ac8SNicholas Roth goto unlock_and_return; 1386*e14d3ac8SNicholas Roth 1387*e14d3ac8SNicholas Roth ret = ov8858_start_stream(ov8858, state); 1388*e14d3ac8SNicholas Roth if (ret) { 1389*e14d3ac8SNicholas Roth dev_err(&client->dev, "Failed to start streaming\n"); 1390*e14d3ac8SNicholas Roth pm_runtime_put_sync(&client->dev); 1391*e14d3ac8SNicholas Roth goto unlock_and_return; 1392*e14d3ac8SNicholas Roth } 1393*e14d3ac8SNicholas Roth } else { 1394*e14d3ac8SNicholas Roth ov8858_stop_stream(ov8858); 1395*e14d3ac8SNicholas Roth pm_runtime_mark_last_busy(&client->dev); 1396*e14d3ac8SNicholas Roth pm_runtime_put_autosuspend(&client->dev); 1397*e14d3ac8SNicholas Roth } 1398*e14d3ac8SNicholas Roth 1399*e14d3ac8SNicholas Roth unlock_and_return: 1400*e14d3ac8SNicholas Roth v4l2_subdev_unlock_state(state); 1401*e14d3ac8SNicholas Roth 1402*e14d3ac8SNicholas Roth return ret; 1403*e14d3ac8SNicholas Roth } 1404*e14d3ac8SNicholas Roth 1405*e14d3ac8SNicholas Roth static const struct v4l2_subdev_video_ops ov8858_video_ops = { 1406*e14d3ac8SNicholas Roth .s_stream = ov8858_s_stream, 1407*e14d3ac8SNicholas Roth }; 1408*e14d3ac8SNicholas Roth 1409*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1410*e14d3ac8SNicholas Roth * Pad ops 1411*e14d3ac8SNicholas Roth */ 1412*e14d3ac8SNicholas Roth 1413*e14d3ac8SNicholas Roth static int ov8858_set_fmt(struct v4l2_subdev *sd, 1414*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state, 1415*e14d3ac8SNicholas Roth struct v4l2_subdev_format *fmt) 1416*e14d3ac8SNicholas Roth { 1417*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = sd_to_ov8858(sd); 1418*e14d3ac8SNicholas Roth const struct ov8858_mode *mode; 1419*e14d3ac8SNicholas Roth s64 h_blank, vblank_def; 1420*e14d3ac8SNicholas Roth 1421*e14d3ac8SNicholas Roth mode = v4l2_find_nearest_size(ov8858_modes, ARRAY_SIZE(ov8858_modes), 1422*e14d3ac8SNicholas Roth width, height, fmt->format.width, 1423*e14d3ac8SNicholas Roth fmt->format.height); 1424*e14d3ac8SNicholas Roth 1425*e14d3ac8SNicholas Roth fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; 1426*e14d3ac8SNicholas Roth fmt->format.width = mode->width; 1427*e14d3ac8SNicholas Roth fmt->format.height = mode->height; 1428*e14d3ac8SNicholas Roth fmt->format.field = V4L2_FIELD_NONE; 1429*e14d3ac8SNicholas Roth 1430*e14d3ac8SNicholas Roth /* Store the format in the current subdev state. */ 1431*e14d3ac8SNicholas Roth *v4l2_subdev_get_pad_format(sd, state, 0) = fmt->format; 1432*e14d3ac8SNicholas Roth 1433*e14d3ac8SNicholas Roth if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) 1434*e14d3ac8SNicholas Roth return 0; 1435*e14d3ac8SNicholas Roth 1436*e14d3ac8SNicholas Roth /* Adjust control limits when a new mode is applied. */ 1437*e14d3ac8SNicholas Roth h_blank = mode->hts_def - mode->width; 1438*e14d3ac8SNicholas Roth __v4l2_ctrl_modify_range(ov8858->hblank, h_blank, h_blank, 1, 1439*e14d3ac8SNicholas Roth h_blank); 1440*e14d3ac8SNicholas Roth 1441*e14d3ac8SNicholas Roth vblank_def = mode->vts_def - mode->height; 1442*e14d3ac8SNicholas Roth __v4l2_ctrl_modify_range(ov8858->vblank, vblank_def, 1443*e14d3ac8SNicholas Roth OV8858_VTS_MAX - mode->height, 1, 1444*e14d3ac8SNicholas Roth vblank_def); 1445*e14d3ac8SNicholas Roth 1446*e14d3ac8SNicholas Roth return 0; 1447*e14d3ac8SNicholas Roth } 1448*e14d3ac8SNicholas Roth 1449*e14d3ac8SNicholas Roth static int ov8858_enum_frame_sizes(struct v4l2_subdev *sd, 1450*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state, 1451*e14d3ac8SNicholas Roth struct v4l2_subdev_frame_size_enum *fse) 1452*e14d3ac8SNicholas Roth { 1453*e14d3ac8SNicholas Roth if (fse->index >= ARRAY_SIZE(ov8858_modes)) 1454*e14d3ac8SNicholas Roth return -EINVAL; 1455*e14d3ac8SNicholas Roth 1456*e14d3ac8SNicholas Roth if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) 1457*e14d3ac8SNicholas Roth return -EINVAL; 1458*e14d3ac8SNicholas Roth 1459*e14d3ac8SNicholas Roth fse->min_width = ov8858_modes[fse->index].width; 1460*e14d3ac8SNicholas Roth fse->max_width = ov8858_modes[fse->index].width; 1461*e14d3ac8SNicholas Roth fse->max_height = ov8858_modes[fse->index].height; 1462*e14d3ac8SNicholas Roth fse->min_height = ov8858_modes[fse->index].height; 1463*e14d3ac8SNicholas Roth 1464*e14d3ac8SNicholas Roth return 0; 1465*e14d3ac8SNicholas Roth } 1466*e14d3ac8SNicholas Roth 1467*e14d3ac8SNicholas Roth static int ov8858_enum_mbus_code(struct v4l2_subdev *sd, 1468*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state, 1469*e14d3ac8SNicholas Roth struct v4l2_subdev_mbus_code_enum *code) 1470*e14d3ac8SNicholas Roth { 1471*e14d3ac8SNicholas Roth if (code->index != 0) 1472*e14d3ac8SNicholas Roth return -EINVAL; 1473*e14d3ac8SNicholas Roth 1474*e14d3ac8SNicholas Roth code->code = MEDIA_BUS_FMT_SBGGR10_1X10; 1475*e14d3ac8SNicholas Roth 1476*e14d3ac8SNicholas Roth return 0; 1477*e14d3ac8SNicholas Roth } 1478*e14d3ac8SNicholas Roth 1479*e14d3ac8SNicholas Roth static int ov8858_init_cfg(struct v4l2_subdev *sd, 1480*e14d3ac8SNicholas Roth struct v4l2_subdev_state *sd_state) 1481*e14d3ac8SNicholas Roth { 1482*e14d3ac8SNicholas Roth const struct ov8858_mode *def_mode = &ov8858_modes[0]; 1483*e14d3ac8SNicholas Roth struct v4l2_subdev_format fmt = { 1484*e14d3ac8SNicholas Roth .which = V4L2_SUBDEV_FORMAT_TRY, 1485*e14d3ac8SNicholas Roth .format = { 1486*e14d3ac8SNicholas Roth .width = def_mode->width, 1487*e14d3ac8SNicholas Roth .height = def_mode->height, 1488*e14d3ac8SNicholas Roth }, 1489*e14d3ac8SNicholas Roth }; 1490*e14d3ac8SNicholas Roth 1491*e14d3ac8SNicholas Roth ov8858_set_fmt(sd, sd_state, &fmt); 1492*e14d3ac8SNicholas Roth 1493*e14d3ac8SNicholas Roth return 0; 1494*e14d3ac8SNicholas Roth } 1495*e14d3ac8SNicholas Roth 1496*e14d3ac8SNicholas Roth static const struct v4l2_subdev_pad_ops ov8858_pad_ops = { 1497*e14d3ac8SNicholas Roth .init_cfg = ov8858_init_cfg, 1498*e14d3ac8SNicholas Roth .enum_mbus_code = ov8858_enum_mbus_code, 1499*e14d3ac8SNicholas Roth .enum_frame_size = ov8858_enum_frame_sizes, 1500*e14d3ac8SNicholas Roth .get_fmt = v4l2_subdev_get_fmt, 1501*e14d3ac8SNicholas Roth .set_fmt = ov8858_set_fmt, 1502*e14d3ac8SNicholas Roth }; 1503*e14d3ac8SNicholas Roth 1504*e14d3ac8SNicholas Roth static const struct v4l2_subdev_core_ops ov8858_core_ops = { 1505*e14d3ac8SNicholas Roth .subscribe_event = v4l2_ctrl_subdev_subscribe_event, 1506*e14d3ac8SNicholas Roth .unsubscribe_event = v4l2_event_subdev_unsubscribe, 1507*e14d3ac8SNicholas Roth }; 1508*e14d3ac8SNicholas Roth 1509*e14d3ac8SNicholas Roth static const struct v4l2_subdev_ops ov8858_subdev_ops = { 1510*e14d3ac8SNicholas Roth .core = &ov8858_core_ops, 1511*e14d3ac8SNicholas Roth .video = &ov8858_video_ops, 1512*e14d3ac8SNicholas Roth .pad = &ov8858_pad_ops, 1513*e14d3ac8SNicholas Roth }; 1514*e14d3ac8SNicholas Roth 1515*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1516*e14d3ac8SNicholas Roth * Controls handling 1517*e14d3ac8SNicholas Roth */ 1518*e14d3ac8SNicholas Roth 1519*e14d3ac8SNicholas Roth static int ov8858_enable_test_pattern(struct ov8858 *ov8858, u32 pattern) 1520*e14d3ac8SNicholas Roth { 1521*e14d3ac8SNicholas Roth u32 val; 1522*e14d3ac8SNicholas Roth 1523*e14d3ac8SNicholas Roth if (pattern) 1524*e14d3ac8SNicholas Roth val = (pattern - 1) | OV8858_TEST_PATTERN_ENABLE; 1525*e14d3ac8SNicholas Roth else 1526*e14d3ac8SNicholas Roth val = OV8858_TEST_PATTERN_DISABLE; 1527*e14d3ac8SNicholas Roth 1528*e14d3ac8SNicholas Roth return ov8858_write(ov8858, OV8858_REG_TEST_PATTERN, val, NULL); 1529*e14d3ac8SNicholas Roth } 1530*e14d3ac8SNicholas Roth 1531*e14d3ac8SNicholas Roth static int ov8858_set_ctrl(struct v4l2_ctrl *ctrl) 1532*e14d3ac8SNicholas Roth { 1533*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = container_of(ctrl->handler, 1534*e14d3ac8SNicholas Roth struct ov8858, ctrl_handler); 1535*e14d3ac8SNicholas Roth 1536*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1537*e14d3ac8SNicholas Roth struct v4l2_mbus_framefmt *format; 1538*e14d3ac8SNicholas Roth struct v4l2_subdev_state *state; 1539*e14d3ac8SNicholas Roth u16 digi_gain; 1540*e14d3ac8SNicholas Roth s64 max_exp; 1541*e14d3ac8SNicholas Roth int ret; 1542*e14d3ac8SNicholas Roth 1543*e14d3ac8SNicholas Roth /* 1544*e14d3ac8SNicholas Roth * The control handler and the subdev state use the same mutex and the 1545*e14d3ac8SNicholas Roth * mutex is guaranteed to be locked: 1546*e14d3ac8SNicholas Roth * - by the core when s_ctrl is called int the VIDIOC_S_CTRL call path 1547*e14d3ac8SNicholas Roth * - by the driver when s_ctrl is called in the s_stream(1) call path 1548*e14d3ac8SNicholas Roth */ 1549*e14d3ac8SNicholas Roth state = v4l2_subdev_get_locked_active_state(&ov8858->subdev); 1550*e14d3ac8SNicholas Roth format = v4l2_subdev_get_pad_format(&ov8858->subdev, state, 0); 1551*e14d3ac8SNicholas Roth 1552*e14d3ac8SNicholas Roth /* Propagate change of current control to all related controls */ 1553*e14d3ac8SNicholas Roth switch (ctrl->id) { 1554*e14d3ac8SNicholas Roth case V4L2_CID_VBLANK: 1555*e14d3ac8SNicholas Roth /* Update max exposure while meeting expected vblanking */ 1556*e14d3ac8SNicholas Roth max_exp = format->height + ctrl->val - OV8858_EXPOSURE_MARGIN; 1557*e14d3ac8SNicholas Roth __v4l2_ctrl_modify_range(ov8858->exposure, 1558*e14d3ac8SNicholas Roth ov8858->exposure->minimum, max_exp, 1559*e14d3ac8SNicholas Roth ov8858->exposure->step, 1560*e14d3ac8SNicholas Roth ov8858->exposure->default_value); 1561*e14d3ac8SNicholas Roth break; 1562*e14d3ac8SNicholas Roth } 1563*e14d3ac8SNicholas Roth 1564*e14d3ac8SNicholas Roth if (!pm_runtime_get_if_in_use(&client->dev)) 1565*e14d3ac8SNicholas Roth return 0; 1566*e14d3ac8SNicholas Roth 1567*e14d3ac8SNicholas Roth switch (ctrl->id) { 1568*e14d3ac8SNicholas Roth case V4L2_CID_EXPOSURE: 1569*e14d3ac8SNicholas Roth /* 4 least significant bits of exposure are fractional part */ 1570*e14d3ac8SNicholas Roth ret = ov8858_write(ov8858, OV8858_REG_LONG_EXPO, 1571*e14d3ac8SNicholas Roth ctrl->val << 4, NULL); 1572*e14d3ac8SNicholas Roth break; 1573*e14d3ac8SNicholas Roth case V4L2_CID_ANALOGUE_GAIN: 1574*e14d3ac8SNicholas Roth ret = ov8858_write(ov8858, OV8858_REG_LONG_GAIN, 1575*e14d3ac8SNicholas Roth ctrl->val, NULL); 1576*e14d3ac8SNicholas Roth break; 1577*e14d3ac8SNicholas Roth case V4L2_CID_DIGITAL_GAIN: 1578*e14d3ac8SNicholas Roth /* 1579*e14d3ac8SNicholas Roth * Digital gain is assembled as: 1580*e14d3ac8SNicholas Roth * 0x350a[7:0] = dgain[13:6] 1581*e14d3ac8SNicholas Roth * 0x350b[5:0] = dgain[5:0] 1582*e14d3ac8SNicholas Roth * Reassemble the control value to write it in one go. 1583*e14d3ac8SNicholas Roth */ 1584*e14d3ac8SNicholas Roth digi_gain = (ctrl->val & OV8858_LONG_DIGIGAIN_L_MASK) 1585*e14d3ac8SNicholas Roth | ((ctrl->val & OV8858_LONG_DIGIGAIN_H_MASK) << 1586*e14d3ac8SNicholas Roth OV8858_LONG_DIGIGAIN_H_SHIFT); 1587*e14d3ac8SNicholas Roth ret = ov8858_write(ov8858, OV8858_REG_LONG_DIGIGAIN, 1588*e14d3ac8SNicholas Roth digi_gain, NULL); 1589*e14d3ac8SNicholas Roth break; 1590*e14d3ac8SNicholas Roth case V4L2_CID_VBLANK: 1591*e14d3ac8SNicholas Roth ret = ov8858_write(ov8858, OV8858_REG_VTS, 1592*e14d3ac8SNicholas Roth ctrl->val + format->height, NULL); 1593*e14d3ac8SNicholas Roth break; 1594*e14d3ac8SNicholas Roth case V4L2_CID_TEST_PATTERN: 1595*e14d3ac8SNicholas Roth ret = ov8858_enable_test_pattern(ov8858, ctrl->val); 1596*e14d3ac8SNicholas Roth break; 1597*e14d3ac8SNicholas Roth default: 1598*e14d3ac8SNicholas Roth ret = -EINVAL; 1599*e14d3ac8SNicholas Roth dev_warn(&client->dev, "%s Unhandled id: 0x%x\n", 1600*e14d3ac8SNicholas Roth __func__, ctrl->id); 1601*e14d3ac8SNicholas Roth break; 1602*e14d3ac8SNicholas Roth } 1603*e14d3ac8SNicholas Roth 1604*e14d3ac8SNicholas Roth pm_runtime_put(&client->dev); 1605*e14d3ac8SNicholas Roth 1606*e14d3ac8SNicholas Roth return ret; 1607*e14d3ac8SNicholas Roth } 1608*e14d3ac8SNicholas Roth 1609*e14d3ac8SNicholas Roth static const struct v4l2_ctrl_ops ov8858_ctrl_ops = { 1610*e14d3ac8SNicholas Roth .s_ctrl = ov8858_set_ctrl, 1611*e14d3ac8SNicholas Roth }; 1612*e14d3ac8SNicholas Roth 1613*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1614*e14d3ac8SNicholas Roth * Power Management 1615*e14d3ac8SNicholas Roth */ 1616*e14d3ac8SNicholas Roth 1617*e14d3ac8SNicholas Roth static int ov8858_power_on(struct ov8858 *ov8858) 1618*e14d3ac8SNicholas Roth { 1619*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1620*e14d3ac8SNicholas Roth struct device *dev = &client->dev; 1621*e14d3ac8SNicholas Roth unsigned long delay_us; 1622*e14d3ac8SNicholas Roth int ret; 1623*e14d3ac8SNicholas Roth 1624*e14d3ac8SNicholas Roth if (clk_get_rate(ov8858->xvclk) != OV8858_XVCLK_FREQ) 1625*e14d3ac8SNicholas Roth dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); 1626*e14d3ac8SNicholas Roth 1627*e14d3ac8SNicholas Roth ret = clk_prepare_enable(ov8858->xvclk); 1628*e14d3ac8SNicholas Roth if (ret < 0) { 1629*e14d3ac8SNicholas Roth dev_err(dev, "Failed to enable xvclk\n"); 1630*e14d3ac8SNicholas Roth return ret; 1631*e14d3ac8SNicholas Roth } 1632*e14d3ac8SNicholas Roth 1633*e14d3ac8SNicholas Roth ret = regulator_bulk_enable(ARRAY_SIZE(ov8858_supply_names), 1634*e14d3ac8SNicholas Roth ov8858->supplies); 1635*e14d3ac8SNicholas Roth if (ret < 0) { 1636*e14d3ac8SNicholas Roth dev_err(dev, "Failed to enable regulators\n"); 1637*e14d3ac8SNicholas Roth goto disable_clk; 1638*e14d3ac8SNicholas Roth } 1639*e14d3ac8SNicholas Roth 1640*e14d3ac8SNicholas Roth /* 1641*e14d3ac8SNicholas Roth * The chip manual only suggests 8192 cycles prior to first SCCB 1642*e14d3ac8SNicholas Roth * transaction, but a double sleep between the release of gpios 1643*e14d3ac8SNicholas Roth * helps with sporadic failures observed at probe time. 1644*e14d3ac8SNicholas Roth */ 1645*e14d3ac8SNicholas Roth delay_us = DIV_ROUND_UP(8192, OV8858_XVCLK_FREQ / 1000 / 1000); 1646*e14d3ac8SNicholas Roth 1647*e14d3ac8SNicholas Roth gpiod_set_value_cansleep(ov8858->reset_gpio, 0); 1648*e14d3ac8SNicholas Roth fsleep(delay_us); 1649*e14d3ac8SNicholas Roth gpiod_set_value_cansleep(ov8858->pwdn_gpio, 0); 1650*e14d3ac8SNicholas Roth fsleep(delay_us); 1651*e14d3ac8SNicholas Roth 1652*e14d3ac8SNicholas Roth return 0; 1653*e14d3ac8SNicholas Roth 1654*e14d3ac8SNicholas Roth disable_clk: 1655*e14d3ac8SNicholas Roth clk_disable_unprepare(ov8858->xvclk); 1656*e14d3ac8SNicholas Roth 1657*e14d3ac8SNicholas Roth return ret; 1658*e14d3ac8SNicholas Roth } 1659*e14d3ac8SNicholas Roth 1660*e14d3ac8SNicholas Roth static void ov8858_power_off(struct ov8858 *ov8858) 1661*e14d3ac8SNicholas Roth { 1662*e14d3ac8SNicholas Roth gpiod_set_value_cansleep(ov8858->pwdn_gpio, 1); 1663*e14d3ac8SNicholas Roth clk_disable_unprepare(ov8858->xvclk); 1664*e14d3ac8SNicholas Roth gpiod_set_value_cansleep(ov8858->reset_gpio, 1); 1665*e14d3ac8SNicholas Roth 1666*e14d3ac8SNicholas Roth regulator_bulk_disable(ARRAY_SIZE(ov8858_supply_names), 1667*e14d3ac8SNicholas Roth ov8858->supplies); 1668*e14d3ac8SNicholas Roth } 1669*e14d3ac8SNicholas Roth 1670*e14d3ac8SNicholas Roth static int ov8858_runtime_resume(struct device *dev) 1671*e14d3ac8SNicholas Roth { 1672*e14d3ac8SNicholas Roth struct i2c_client *client = to_i2c_client(dev); 1673*e14d3ac8SNicholas Roth struct v4l2_subdev *sd = i2c_get_clientdata(client); 1674*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = sd_to_ov8858(sd); 1675*e14d3ac8SNicholas Roth 1676*e14d3ac8SNicholas Roth return ov8858_power_on(ov8858); 1677*e14d3ac8SNicholas Roth } 1678*e14d3ac8SNicholas Roth 1679*e14d3ac8SNicholas Roth static int ov8858_runtime_suspend(struct device *dev) 1680*e14d3ac8SNicholas Roth { 1681*e14d3ac8SNicholas Roth struct i2c_client *client = to_i2c_client(dev); 1682*e14d3ac8SNicholas Roth struct v4l2_subdev *sd = i2c_get_clientdata(client); 1683*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = sd_to_ov8858(sd); 1684*e14d3ac8SNicholas Roth 1685*e14d3ac8SNicholas Roth ov8858_power_off(ov8858); 1686*e14d3ac8SNicholas Roth 1687*e14d3ac8SNicholas Roth return 0; 1688*e14d3ac8SNicholas Roth } 1689*e14d3ac8SNicholas Roth 1690*e14d3ac8SNicholas Roth static const struct dev_pm_ops ov8858_pm_ops = { 1691*e14d3ac8SNicholas Roth SET_RUNTIME_PM_OPS(ov8858_runtime_suspend, 1692*e14d3ac8SNicholas Roth ov8858_runtime_resume, NULL) 1693*e14d3ac8SNicholas Roth }; 1694*e14d3ac8SNicholas Roth 1695*e14d3ac8SNicholas Roth /* ---------------------------------------------------------------------------- 1696*e14d3ac8SNicholas Roth * Probe and initialization 1697*e14d3ac8SNicholas Roth */ 1698*e14d3ac8SNicholas Roth 1699*e14d3ac8SNicholas Roth static int ov8858_init_ctrls(struct ov8858 *ov8858) 1700*e14d3ac8SNicholas Roth { 1701*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1702*e14d3ac8SNicholas Roth struct v4l2_ctrl_handler *handler = &ov8858->ctrl_handler; 1703*e14d3ac8SNicholas Roth const struct ov8858_mode *mode = &ov8858_modes[0]; 1704*e14d3ac8SNicholas Roth struct v4l2_fwnode_device_properties props; 1705*e14d3ac8SNicholas Roth s64 exposure_max, vblank_def; 1706*e14d3ac8SNicholas Roth unsigned int pixel_rate; 1707*e14d3ac8SNicholas Roth struct v4l2_ctrl *ctrl; 1708*e14d3ac8SNicholas Roth u32 h_blank; 1709*e14d3ac8SNicholas Roth int ret; 1710*e14d3ac8SNicholas Roth 1711*e14d3ac8SNicholas Roth ret = v4l2_ctrl_handler_init(handler, 10); 1712*e14d3ac8SNicholas Roth if (ret) 1713*e14d3ac8SNicholas Roth return ret; 1714*e14d3ac8SNicholas Roth 1715*e14d3ac8SNicholas Roth ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, 1716*e14d3ac8SNicholas Roth 0, 0, link_freq_menu_items); 1717*e14d3ac8SNicholas Roth if (ctrl) 1718*e14d3ac8SNicholas Roth ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 1719*e14d3ac8SNicholas Roth 1720*e14d3ac8SNicholas Roth /* pixel rate = link frequency * 2 * lanes / bpp */ 1721*e14d3ac8SNicholas Roth pixel_rate = OV8858_LINK_FREQ * 2 * ov8858->num_lanes / 10; 1722*e14d3ac8SNicholas Roth v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1723*e14d3ac8SNicholas Roth 0, pixel_rate, 1, pixel_rate); 1724*e14d3ac8SNicholas Roth 1725*e14d3ac8SNicholas Roth h_blank = mode->hts_def - mode->width; 1726*e14d3ac8SNicholas Roth ov8858->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, 1727*e14d3ac8SNicholas Roth h_blank, h_blank, 1, h_blank); 1728*e14d3ac8SNicholas Roth if (ov8858->hblank) 1729*e14d3ac8SNicholas Roth ov8858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; 1730*e14d3ac8SNicholas Roth 1731*e14d3ac8SNicholas Roth vblank_def = mode->vts_def - mode->height; 1732*e14d3ac8SNicholas Roth ov8858->vblank = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, 1733*e14d3ac8SNicholas Roth V4L2_CID_VBLANK, vblank_def, 1734*e14d3ac8SNicholas Roth OV8858_VTS_MAX - mode->height, 1735*e14d3ac8SNicholas Roth 1, vblank_def); 1736*e14d3ac8SNicholas Roth 1737*e14d3ac8SNicholas Roth exposure_max = mode->vts_def - OV8858_EXPOSURE_MARGIN; 1738*e14d3ac8SNicholas Roth ov8858->exposure = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, 1739*e14d3ac8SNicholas Roth V4L2_CID_EXPOSURE, 1740*e14d3ac8SNicholas Roth OV8858_EXPOSURE_MIN, 1741*e14d3ac8SNicholas Roth exposure_max, OV8858_EXPOSURE_STEP, 1742*e14d3ac8SNicholas Roth mode->exp_def); 1743*e14d3ac8SNicholas Roth 1744*e14d3ac8SNicholas Roth v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, 1745*e14d3ac8SNicholas Roth OV8858_LONG_GAIN_MIN, OV8858_LONG_GAIN_MAX, 1746*e14d3ac8SNicholas Roth OV8858_LONG_GAIN_STEP, OV8858_LONG_GAIN_DEFAULT); 1747*e14d3ac8SNicholas Roth 1748*e14d3ac8SNicholas Roth v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, V4L2_CID_DIGITAL_GAIN, 1749*e14d3ac8SNicholas Roth OV8858_LONG_DIGIGAIN_MIN, OV8858_LONG_DIGIGAIN_MAX, 1750*e14d3ac8SNicholas Roth OV8858_LONG_DIGIGAIN_STEP, 1751*e14d3ac8SNicholas Roth OV8858_LONG_DIGIGAIN_DEFAULT); 1752*e14d3ac8SNicholas Roth 1753*e14d3ac8SNicholas Roth v4l2_ctrl_new_std_menu_items(handler, &ov8858_ctrl_ops, 1754*e14d3ac8SNicholas Roth V4L2_CID_TEST_PATTERN, 1755*e14d3ac8SNicholas Roth ARRAY_SIZE(ov8858_test_pattern_menu) - 1, 1756*e14d3ac8SNicholas Roth 0, 0, ov8858_test_pattern_menu); 1757*e14d3ac8SNicholas Roth 1758*e14d3ac8SNicholas Roth if (handler->error) { 1759*e14d3ac8SNicholas Roth ret = handler->error; 1760*e14d3ac8SNicholas Roth goto err_free_handler; 1761*e14d3ac8SNicholas Roth } 1762*e14d3ac8SNicholas Roth 1763*e14d3ac8SNicholas Roth ret = v4l2_fwnode_device_parse(&client->dev, &props); 1764*e14d3ac8SNicholas Roth if (ret) 1765*e14d3ac8SNicholas Roth goto err_free_handler; 1766*e14d3ac8SNicholas Roth 1767*e14d3ac8SNicholas Roth ret = v4l2_ctrl_new_fwnode_properties(handler, &ov8858_ctrl_ops, 1768*e14d3ac8SNicholas Roth &props); 1769*e14d3ac8SNicholas Roth if (ret) 1770*e14d3ac8SNicholas Roth goto err_free_handler; 1771*e14d3ac8SNicholas Roth 1772*e14d3ac8SNicholas Roth ov8858->subdev.ctrl_handler = handler; 1773*e14d3ac8SNicholas Roth 1774*e14d3ac8SNicholas Roth return 0; 1775*e14d3ac8SNicholas Roth 1776*e14d3ac8SNicholas Roth err_free_handler: 1777*e14d3ac8SNicholas Roth dev_err(&client->dev, "Failed to init controls: %d\n", ret); 1778*e14d3ac8SNicholas Roth v4l2_ctrl_handler_free(handler); 1779*e14d3ac8SNicholas Roth 1780*e14d3ac8SNicholas Roth return ret; 1781*e14d3ac8SNicholas Roth } 1782*e14d3ac8SNicholas Roth 1783*e14d3ac8SNicholas Roth static int ov8858_check_sensor_id(struct ov8858 *ov8858) 1784*e14d3ac8SNicholas Roth { 1785*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1786*e14d3ac8SNicholas Roth u32 id = 0; 1787*e14d3ac8SNicholas Roth int ret; 1788*e14d3ac8SNicholas Roth 1789*e14d3ac8SNicholas Roth ret = ov8858_read(ov8858, OV8858_REG_CHIP_ID, &id); 1790*e14d3ac8SNicholas Roth if (ret) 1791*e14d3ac8SNicholas Roth return ret; 1792*e14d3ac8SNicholas Roth 1793*e14d3ac8SNicholas Roth if (id != OV8858_CHIP_ID) { 1794*e14d3ac8SNicholas Roth dev_err(&client->dev, "Unexpected sensor id 0x%x\n", id); 1795*e14d3ac8SNicholas Roth return -ENODEV; 1796*e14d3ac8SNicholas Roth } 1797*e14d3ac8SNicholas Roth 1798*e14d3ac8SNicholas Roth ret = ov8858_read(ov8858, OV8858_REG_SUB_ID, &id); 1799*e14d3ac8SNicholas Roth if (ret) 1800*e14d3ac8SNicholas Roth return ret; 1801*e14d3ac8SNicholas Roth 1802*e14d3ac8SNicholas Roth dev_info(&client->dev, "Detected OV8858 sensor, revision 0x%x\n", id); 1803*e14d3ac8SNicholas Roth 1804*e14d3ac8SNicholas Roth if (id == OV8858_R2A) { 1805*e14d3ac8SNicholas Roth /* R2A supports 2 and 4 lanes modes. */ 1806*e14d3ac8SNicholas Roth ov8858->global_regs = ov8858->num_lanes == 4 1807*e14d3ac8SNicholas Roth ? ov8858_global_regs_r2a_4lane 1808*e14d3ac8SNicholas Roth : ov8858_global_regs_r2a_2lane; 1809*e14d3ac8SNicholas Roth } else if (ov8858->num_lanes == 2) { 1810*e14d3ac8SNicholas Roth /* 1811*e14d3ac8SNicholas Roth * R1A only supports 2 lanes mode and it's only partially 1812*e14d3ac8SNicholas Roth * supported. 1813*e14d3ac8SNicholas Roth */ 1814*e14d3ac8SNicholas Roth ov8858->global_regs = ov8858_global_regs_r1a; 1815*e14d3ac8SNicholas Roth dev_warn(&client->dev, "R1A may not work well!\n"); 1816*e14d3ac8SNicholas Roth } else { 1817*e14d3ac8SNicholas Roth dev_err(&client->dev, 1818*e14d3ac8SNicholas Roth "Unsupported number of data lanes for R1A revision.\n"); 1819*e14d3ac8SNicholas Roth return -EINVAL; 1820*e14d3ac8SNicholas Roth } 1821*e14d3ac8SNicholas Roth 1822*e14d3ac8SNicholas Roth return 0; 1823*e14d3ac8SNicholas Roth } 1824*e14d3ac8SNicholas Roth 1825*e14d3ac8SNicholas Roth static int ov8858_configure_regulators(struct ov8858 *ov8858) 1826*e14d3ac8SNicholas Roth { 1827*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1828*e14d3ac8SNicholas Roth unsigned int i; 1829*e14d3ac8SNicholas Roth 1830*e14d3ac8SNicholas Roth for (i = 0; i < ARRAY_SIZE(ov8858_supply_names); i++) 1831*e14d3ac8SNicholas Roth ov8858->supplies[i].supply = ov8858_supply_names[i]; 1832*e14d3ac8SNicholas Roth 1833*e14d3ac8SNicholas Roth return devm_regulator_bulk_get(&client->dev, 1834*e14d3ac8SNicholas Roth ARRAY_SIZE(ov8858_supply_names), 1835*e14d3ac8SNicholas Roth ov8858->supplies); 1836*e14d3ac8SNicholas Roth } 1837*e14d3ac8SNicholas Roth 1838*e14d3ac8SNicholas Roth static int ov8858_parse_of(struct ov8858 *ov8858) 1839*e14d3ac8SNicholas Roth { 1840*e14d3ac8SNicholas Roth struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; 1841*e14d3ac8SNicholas Roth struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev); 1842*e14d3ac8SNicholas Roth struct device *dev = &client->dev; 1843*e14d3ac8SNicholas Roth struct fwnode_handle *endpoint; 1844*e14d3ac8SNicholas Roth int ret; 1845*e14d3ac8SNicholas Roth 1846*e14d3ac8SNicholas Roth endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); 1847*e14d3ac8SNicholas Roth if (!endpoint) { 1848*e14d3ac8SNicholas Roth dev_err(dev, "Failed to get endpoint\n"); 1849*e14d3ac8SNicholas Roth return -EINVAL; 1850*e14d3ac8SNicholas Roth } 1851*e14d3ac8SNicholas Roth 1852*e14d3ac8SNicholas Roth ret = v4l2_fwnode_endpoint_parse(endpoint, &vep); 1853*e14d3ac8SNicholas Roth if (ret) { 1854*e14d3ac8SNicholas Roth dev_err(dev, "Failed to parse endpoint: %d\n", ret); 1855*e14d3ac8SNicholas Roth fwnode_handle_put(endpoint); 1856*e14d3ac8SNicholas Roth return ret; 1857*e14d3ac8SNicholas Roth } 1858*e14d3ac8SNicholas Roth 1859*e14d3ac8SNicholas Roth ov8858->num_lanes = vep.bus.mipi_csi2.num_data_lanes; 1860*e14d3ac8SNicholas Roth switch (ov8858->num_lanes) { 1861*e14d3ac8SNicholas Roth case 4: 1862*e14d3ac8SNicholas Roth case 2: 1863*e14d3ac8SNicholas Roth break; 1864*e14d3ac8SNicholas Roth default: 1865*e14d3ac8SNicholas Roth dev_err(dev, "Unsupported number of data lanes %u\n", 1866*e14d3ac8SNicholas Roth ov8858->num_lanes); 1867*e14d3ac8SNicholas Roth fwnode_handle_put(endpoint); 1868*e14d3ac8SNicholas Roth return -EINVAL; 1869*e14d3ac8SNicholas Roth } 1870*e14d3ac8SNicholas Roth 1871*e14d3ac8SNicholas Roth ov8858->subdev.fwnode = endpoint; 1872*e14d3ac8SNicholas Roth 1873*e14d3ac8SNicholas Roth return 0; 1874*e14d3ac8SNicholas Roth } 1875*e14d3ac8SNicholas Roth 1876*e14d3ac8SNicholas Roth static int ov8858_probe(struct i2c_client *client) 1877*e14d3ac8SNicholas Roth { 1878*e14d3ac8SNicholas Roth struct device *dev = &client->dev; 1879*e14d3ac8SNicholas Roth struct v4l2_subdev *sd; 1880*e14d3ac8SNicholas Roth struct ov8858 *ov8858; 1881*e14d3ac8SNicholas Roth int ret; 1882*e14d3ac8SNicholas Roth 1883*e14d3ac8SNicholas Roth ov8858 = devm_kzalloc(dev, sizeof(*ov8858), GFP_KERNEL); 1884*e14d3ac8SNicholas Roth if (!ov8858) 1885*e14d3ac8SNicholas Roth return -ENOMEM; 1886*e14d3ac8SNicholas Roth 1887*e14d3ac8SNicholas Roth ov8858->xvclk = devm_clk_get(dev, "xvclk"); 1888*e14d3ac8SNicholas Roth if (IS_ERR(ov8858->xvclk)) 1889*e14d3ac8SNicholas Roth return dev_err_probe(dev, PTR_ERR(ov8858->xvclk), 1890*e14d3ac8SNicholas Roth "Failed to get xvclk\n"); 1891*e14d3ac8SNicholas Roth 1892*e14d3ac8SNicholas Roth ov8858->reset_gpio = devm_gpiod_get_optional(dev, "reset", 1893*e14d3ac8SNicholas Roth GPIOD_OUT_HIGH); 1894*e14d3ac8SNicholas Roth if (IS_ERR(ov8858->reset_gpio)) 1895*e14d3ac8SNicholas Roth return dev_err_probe(dev, PTR_ERR(ov8858->reset_gpio), 1896*e14d3ac8SNicholas Roth "Failed to get reset gpio\n"); 1897*e14d3ac8SNicholas Roth 1898*e14d3ac8SNicholas Roth ov8858->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown", 1899*e14d3ac8SNicholas Roth GPIOD_OUT_HIGH); 1900*e14d3ac8SNicholas Roth if (IS_ERR(ov8858->pwdn_gpio)) 1901*e14d3ac8SNicholas Roth return dev_err_probe(dev, PTR_ERR(ov8858->pwdn_gpio), 1902*e14d3ac8SNicholas Roth "Failed to get powerdown gpio\n"); 1903*e14d3ac8SNicholas Roth 1904*e14d3ac8SNicholas Roth v4l2_i2c_subdev_init(&ov8858->subdev, client, &ov8858_subdev_ops); 1905*e14d3ac8SNicholas Roth 1906*e14d3ac8SNicholas Roth ret = ov8858_configure_regulators(ov8858); 1907*e14d3ac8SNicholas Roth if (ret) 1908*e14d3ac8SNicholas Roth return dev_err_probe(dev, ret, "Failed to get regulators\n"); 1909*e14d3ac8SNicholas Roth 1910*e14d3ac8SNicholas Roth ret = ov8858_parse_of(ov8858); 1911*e14d3ac8SNicholas Roth if (ret) 1912*e14d3ac8SNicholas Roth return ret; 1913*e14d3ac8SNicholas Roth 1914*e14d3ac8SNicholas Roth ret = ov8858_init_ctrls(ov8858); 1915*e14d3ac8SNicholas Roth if (ret) 1916*e14d3ac8SNicholas Roth goto err_put_fwnode; 1917*e14d3ac8SNicholas Roth 1918*e14d3ac8SNicholas Roth sd = &ov8858->subdev; 1919*e14d3ac8SNicholas Roth sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; 1920*e14d3ac8SNicholas Roth ov8858->pad.flags = MEDIA_PAD_FL_SOURCE; 1921*e14d3ac8SNicholas Roth sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; 1922*e14d3ac8SNicholas Roth ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad); 1923*e14d3ac8SNicholas Roth if (ret < 0) 1924*e14d3ac8SNicholas Roth goto err_free_handler; 1925*e14d3ac8SNicholas Roth 1926*e14d3ac8SNicholas Roth sd->state_lock = ov8858->ctrl_handler.lock; 1927*e14d3ac8SNicholas Roth ret = v4l2_subdev_init_finalize(sd); 1928*e14d3ac8SNicholas Roth if (ret < 0) { 1929*e14d3ac8SNicholas Roth dev_err(&client->dev, "Subdev initialization error %d\n", ret); 1930*e14d3ac8SNicholas Roth goto err_clean_entity; 1931*e14d3ac8SNicholas Roth } 1932*e14d3ac8SNicholas Roth 1933*e14d3ac8SNicholas Roth ret = ov8858_power_on(ov8858); 1934*e14d3ac8SNicholas Roth if (ret) 1935*e14d3ac8SNicholas Roth goto err_clean_entity; 1936*e14d3ac8SNicholas Roth 1937*e14d3ac8SNicholas Roth pm_runtime_set_active(dev); 1938*e14d3ac8SNicholas Roth pm_runtime_get_noresume(dev); 1939*e14d3ac8SNicholas Roth pm_runtime_enable(dev); 1940*e14d3ac8SNicholas Roth 1941*e14d3ac8SNicholas Roth ret = ov8858_check_sensor_id(ov8858); 1942*e14d3ac8SNicholas Roth if (ret) 1943*e14d3ac8SNicholas Roth goto err_power_off; 1944*e14d3ac8SNicholas Roth 1945*e14d3ac8SNicholas Roth pm_runtime_set_autosuspend_delay(dev, 1000); 1946*e14d3ac8SNicholas Roth pm_runtime_use_autosuspend(dev); 1947*e14d3ac8SNicholas Roth 1948*e14d3ac8SNicholas Roth ret = v4l2_async_register_subdev_sensor(sd); 1949*e14d3ac8SNicholas Roth if (ret) { 1950*e14d3ac8SNicholas Roth dev_err(dev, "v4l2 async register subdev failed\n"); 1951*e14d3ac8SNicholas Roth goto err_power_off; 1952*e14d3ac8SNicholas Roth } 1953*e14d3ac8SNicholas Roth 1954*e14d3ac8SNicholas Roth pm_runtime_mark_last_busy(dev); 1955*e14d3ac8SNicholas Roth pm_runtime_put_autosuspend(dev); 1956*e14d3ac8SNicholas Roth 1957*e14d3ac8SNicholas Roth return 0; 1958*e14d3ac8SNicholas Roth 1959*e14d3ac8SNicholas Roth err_power_off: 1960*e14d3ac8SNicholas Roth pm_runtime_disable(dev); 1961*e14d3ac8SNicholas Roth pm_runtime_put_noidle(dev); 1962*e14d3ac8SNicholas Roth ov8858_power_off(ov8858); 1963*e14d3ac8SNicholas Roth err_clean_entity: 1964*e14d3ac8SNicholas Roth media_entity_cleanup(&sd->entity); 1965*e14d3ac8SNicholas Roth err_free_handler: 1966*e14d3ac8SNicholas Roth v4l2_ctrl_handler_free(&ov8858->ctrl_handler); 1967*e14d3ac8SNicholas Roth err_put_fwnode: 1968*e14d3ac8SNicholas Roth fwnode_handle_put(ov8858->subdev.fwnode); 1969*e14d3ac8SNicholas Roth 1970*e14d3ac8SNicholas Roth return ret; 1971*e14d3ac8SNicholas Roth } 1972*e14d3ac8SNicholas Roth 1973*e14d3ac8SNicholas Roth static void ov8858_remove(struct i2c_client *client) 1974*e14d3ac8SNicholas Roth { 1975*e14d3ac8SNicholas Roth struct v4l2_subdev *sd = i2c_get_clientdata(client); 1976*e14d3ac8SNicholas Roth struct ov8858 *ov8858 = sd_to_ov8858(sd); 1977*e14d3ac8SNicholas Roth 1978*e14d3ac8SNicholas Roth v4l2_async_unregister_subdev(sd); 1979*e14d3ac8SNicholas Roth media_entity_cleanup(&sd->entity); 1980*e14d3ac8SNicholas Roth v4l2_ctrl_handler_free(&ov8858->ctrl_handler); 1981*e14d3ac8SNicholas Roth fwnode_handle_put(ov8858->subdev.fwnode); 1982*e14d3ac8SNicholas Roth 1983*e14d3ac8SNicholas Roth pm_runtime_disable(&client->dev); 1984*e14d3ac8SNicholas Roth if (!pm_runtime_status_suspended(&client->dev)) 1985*e14d3ac8SNicholas Roth ov8858_power_off(ov8858); 1986*e14d3ac8SNicholas Roth pm_runtime_set_suspended(&client->dev); 1987*e14d3ac8SNicholas Roth } 1988*e14d3ac8SNicholas Roth 1989*e14d3ac8SNicholas Roth static const struct of_device_id ov8858_of_match[] = { 1990*e14d3ac8SNicholas Roth { .compatible = "ovti,ov8858" }, 1991*e14d3ac8SNicholas Roth { /* sentinel */ }, 1992*e14d3ac8SNicholas Roth }; 1993*e14d3ac8SNicholas Roth MODULE_DEVICE_TABLE(of, ov8858_of_match); 1994*e14d3ac8SNicholas Roth 1995*e14d3ac8SNicholas Roth static struct i2c_driver ov8858_i2c_driver = { 1996*e14d3ac8SNicholas Roth .driver = { 1997*e14d3ac8SNicholas Roth .name = "ov8858", 1998*e14d3ac8SNicholas Roth .pm = &ov8858_pm_ops, 1999*e14d3ac8SNicholas Roth .of_match_table = ov8858_of_match, 2000*e14d3ac8SNicholas Roth }, 2001*e14d3ac8SNicholas Roth .probe_new = &ov8858_probe, 2002*e14d3ac8SNicholas Roth .remove = &ov8858_remove, 2003*e14d3ac8SNicholas Roth }; 2004*e14d3ac8SNicholas Roth 2005*e14d3ac8SNicholas Roth module_i2c_driver(ov8858_i2c_driver); 2006*e14d3ac8SNicholas Roth 2007*e14d3ac8SNicholas Roth MODULE_DESCRIPTION("OmniVision OV8858 sensor driver"); 2008*e14d3ac8SNicholas Roth MODULE_LICENSE("GPL"); 2009