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