2232 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2022 Intel Corporation.3 4#include <linux/unaligned.h>5#include <linux/acpi.h>6#include <linux/i2c.h>7#include <linux/module.h>8#include <linux/delay.h>9#include <linux/pm_runtime.h>10#include <media/v4l2-ctrls.h>11#include <media/v4l2-device.h>12#include <media/v4l2-fwnode.h>13 14#define OV08X40_REG_VALUE_08BIT 115#define OV08X40_REG_VALUE_16BIT 216#define OV08X40_REG_VALUE_24BIT 317 18#define OV08X40_REG_MODE_SELECT 0x010019#define OV08X40_MODE_STANDBY 0x0020#define OV08X40_MODE_STREAMING 0x0121 22#define OV08X40_REG_AO_STANDBY 0x100023#define OV08X40_AO_STREAMING 0x0424 25#define OV08X40_REG_MS_SELECT 0x100126#define OV08X40_MS_STANDBY 0x0027#define OV08X40_MS_STREAMING 0x0428 29#define OV08X40_REG_SOFTWARE_RST 0x010330#define OV08X40_SOFTWARE_RST 0x0131 32/* Chip ID */33#define OV08X40_REG_CHIP_ID 0x300a34#define OV08X40_CHIP_ID 0x56085835 36/* V_TIMING internal */37#define OV08X40_REG_VTS 0x380e38#define OV08X40_VTS_30FPS 0x09c4 /* the VTS need to be half in normal mode */39#define OV08X40_VTS_BIN_30FPS 0x115c40#define OV08X40_VTS_MAX 0x7fff41 42/* H TIMING internal */43#define OV08X40_REG_HTS 0x380c44#define OV08X40_HTS_30FPS 0x028045 46/* Exposure control */47#define OV08X40_REG_EXPOSURE 0x350048#define OV08X40_EXPOSURE_MAX_MARGIN 849#define OV08X40_EXPOSURE_BIN_MAX_MARGIN 250#define OV08X40_EXPOSURE_MIN 451#define OV08X40_EXPOSURE_STEP 152#define OV08X40_EXPOSURE_DEFAULT 0x4053 54/* Short Exposure control */55#define OV08X40_REG_SHORT_EXPOSURE 0x354056 57/* Analog gain control */58#define OV08X40_REG_ANALOG_GAIN 0x350859#define OV08X40_ANA_GAIN_MIN 0x8060#define OV08X40_ANA_GAIN_MAX 0x07c061#define OV08X40_ANA_GAIN_STEP 162#define OV08X40_ANA_GAIN_DEFAULT 0x8063 64/* Digital gain control */65#define OV08X40_REG_DGTL_GAIN_H 0x350a66#define OV08X40_REG_DGTL_GAIN_M 0x350b67#define OV08X40_REG_DGTL_GAIN_L 0x350c68 69#define OV08X40_DGTL_GAIN_MIN 1024 /* Min = 1 X */70#define OV08X40_DGTL_GAIN_MAX (4096 - 1) /* Max = 4 X */71#define OV08X40_DGTL_GAIN_DEFAULT 2560 /* Default gain = 2.5 X */72#define OV08X40_DGTL_GAIN_STEP 1 /* Each step = 1/1024 */73 74#define OV08X40_DGTL_GAIN_L_SHIFT 675#define OV08X40_DGTL_GAIN_L_MASK 0x376#define OV08X40_DGTL_GAIN_M_SHIFT 277#define OV08X40_DGTL_GAIN_M_MASK 0xff78#define OV08X40_DGTL_GAIN_H_SHIFT 1079#define OV08X40_DGTL_GAIN_H_MASK 0x1F80 81/* Test Pattern Control */82#define OV08X40_REG_TEST_PATTERN 0x50C183#define OV08X40_REG_ISP 0x500084#define OV08X40_REG_SHORT_TEST_PATTERN 0x53C185#define OV08X40_TEST_PATTERN_ENABLE BIT(0)86#define OV08X40_TEST_PATTERN_MASK 0xcf87#define OV08X40_TEST_PATTERN_BAR_SHIFT 488 89/* Flip Control */90#define OV08X40_REG_VFLIP 0x382091#define OV08X40_REG_MIRROR 0x382192 93/* Horizontal Window Offset */94#define OV08X40_REG_H_WIN_OFFSET 0x381195 96/* Vertical Window Offset */97#define OV08X40_REG_V_WIN_OFFSET 0x381398 99/* Burst Register */100#define OV08X40_REG_XTALK_FIRST_A 0x5a80101#define OV08X40_REG_XTALK_LAST_A 0x5b9f102#define OV08X40_REG_XTALK_FIRST_B 0x5bc0103#define OV08X40_REG_XTALK_LAST_B 0x5f1f104 105enum {106 OV08X40_LINK_FREQ_400MHZ_INDEX,107};108 109struct ov08x40_reg {110 u16 address;111 u8 val;112};113 114struct ov08x40_reg_list {115 u32 num_of_regs;116 const struct ov08x40_reg *regs;117};118 119/* Link frequency config */120struct ov08x40_link_freq_config {121 /* registers for this link frequency */122 struct ov08x40_reg_list reg_list;123};124 125/* Mode : resolution and related config&values */126struct ov08x40_mode {127 /* Frame width */128 u32 width;129 /* Frame height */130 u32 height;131 132 u32 lanes;133 /* V-timing */134 u32 vts_def;135 u32 vts_min;136 137 /* Line Length Pixels */138 u32 llp;139 140 /* Index of Link frequency config to be used */141 u32 link_freq_index;142 /* Default register values */143 struct ov08x40_reg_list reg_list;144 145 /* Exposure calculation */146 u16 exposure_margin;147 u16 exposure_shift;148};149 150static const struct ov08x40_reg mipi_data_rate_800mbps[] = {151 {0x0103, 0x01},152 {0x1000, 0x00},153 {0x1601, 0xd0},154 {0x1001, 0x04},155 {0x5004, 0x53},156 {0x5110, 0x00},157 {0x5111, 0x14},158 {0x5112, 0x01},159 {0x5113, 0x7b},160 {0x5114, 0x00},161 {0x5152, 0xa3},162 {0x5a52, 0x1f},163 {0x5a1a, 0x0e},164 {0x5a1b, 0x10},165 {0x5a1f, 0x0e},166 {0x5a27, 0x0e},167 {0x6002, 0x2e},168};169 170static const struct ov08x40_reg mode_3856x2416_regs[] = {171 {0x5000, 0x5d},172 {0x5001, 0x20},173 {0x5008, 0xb0},174 {0x50c1, 0x00},175 {0x53c1, 0x00},176 {0x5f40, 0x00},177 {0x5f41, 0x40},178 {0x0300, 0x3a},179 {0x0301, 0xc8},180 {0x0302, 0x31},181 {0x0303, 0x03},182 {0x0304, 0x01},183 {0x0305, 0xa1},184 {0x0306, 0x04},185 {0x0307, 0x01},186 {0x0308, 0x03},187 {0x0309, 0x03},188 {0x0310, 0x0a},189 {0x0311, 0x02},190 {0x0312, 0x01},191 {0x0313, 0x08},192 {0x0314, 0x66},193 {0x0315, 0x00},194 {0x0316, 0x34},195 {0x0320, 0x02},196 {0x0321, 0x03},197 {0x0323, 0x05},198 {0x0324, 0x01},199 {0x0325, 0xb8},200 {0x0326, 0x4a},201 {0x0327, 0x04},202 {0x0329, 0x00},203 {0x032a, 0x05},204 {0x032b, 0x00},205 {0x032c, 0x00},206 {0x032d, 0x00},207 {0x032e, 0x02},208 {0x032f, 0xa0},209 {0x0350, 0x00},210 {0x0360, 0x01},211 {0x1216, 0x60},212 {0x1217, 0x5b},213 {0x1218, 0x00},214 {0x1220, 0x24},215 {0x198a, 0x00},216 {0x198b, 0x01},217 {0x198e, 0x00},218 {0x198f, 0x01},219 {0x3009, 0x04},220 {0x3012, 0x41},221 {0x3015, 0x00},222 {0x3016, 0xb0},223 {0x3017, 0xf0},224 {0x3018, 0xf0},225 {0x3019, 0xd2},226 {0x301a, 0xb0},227 {0x301c, 0x81},228 {0x301d, 0x02},229 {0x301e, 0x80},230 {0x3022, 0xf0},231 {0x3025, 0x89},232 {0x3030, 0x03},233 {0x3044, 0xc2},234 {0x3050, 0x35},235 {0x3051, 0x60},236 {0x3052, 0x25},237 {0x3053, 0x00},238 {0x3054, 0x00},239 {0x3055, 0x02},240 {0x3056, 0x80},241 {0x3057, 0x80},242 {0x3058, 0x80},243 {0x3059, 0x00},244 {0x3107, 0x86},245 {0x3400, 0x1c},246 {0x3401, 0x80},247 {0x3402, 0x8c},248 {0x3419, 0x13},249 {0x341a, 0x89},250 {0x341b, 0x30},251 {0x3420, 0x00},252 {0x3421, 0x00},253 {0x3422, 0x00},254 {0x3423, 0x00},255 {0x3424, 0x00},256 {0x3425, 0x00},257 {0x3426, 0x00},258 {0x3427, 0x00},259 {0x3428, 0x0f},260 {0x3429, 0x00},261 {0x342a, 0x00},262 {0x342b, 0x00},263 {0x342c, 0x00},264 {0x342d, 0x00},265 {0x342e, 0x00},266 {0x342f, 0x11},267 {0x3430, 0x11},268 {0x3431, 0x10},269 {0x3432, 0x00},270 {0x3433, 0x00},271 {0x3434, 0x00},272 {0x3435, 0x00},273 {0x3436, 0x00},274 {0x3437, 0x00},275 {0x3442, 0x02},276 {0x3443, 0x02},277 {0x3444, 0x07},278 {0x3450, 0x00},279 {0x3451, 0x00},280 {0x3452, 0x18},281 {0x3453, 0x18},282 {0x3454, 0x00},283 {0x3455, 0x80},284 {0x3456, 0x08},285 {0x3500, 0x00},286 {0x3501, 0x02},287 {0x3502, 0x00},288 {0x3504, 0x4c},289 {0x3506, 0x30},290 {0x3507, 0x00},291 {0x3508, 0x01},292 {0x3509, 0x00},293 {0x350a, 0x01},294 {0x350b, 0x00},295 {0x350c, 0x00},296 {0x3540, 0x00},297 {0x3541, 0x01},298 {0x3542, 0x00},299 {0x3544, 0x4c},300 {0x3546, 0x30},301 {0x3547, 0x00},302 {0x3548, 0x01},303 {0x3549, 0x00},304 {0x354a, 0x01},305 {0x354b, 0x00},306 {0x354c, 0x00},307 {0x3688, 0x02},308 {0x368a, 0x2e},309 {0x368e, 0x71},310 {0x3696, 0xd1},311 {0x3699, 0x00},312 {0x369a, 0x00},313 {0x36a4, 0x00},314 {0x36a6, 0x00},315 {0x3711, 0x00},316 {0x3712, 0x51},317 {0x3713, 0x00},318 {0x3714, 0x24},319 {0x3716, 0x00},320 {0x3718, 0x07},321 {0x371a, 0x1c},322 {0x371b, 0x00},323 {0x3720, 0x08},324 {0x3725, 0x32},325 {0x3727, 0x05},326 {0x3760, 0x02},327 {0x3761, 0x17},328 {0x3762, 0x02},329 {0x3763, 0x02},330 {0x3764, 0x02},331 {0x3765, 0x2c},332 {0x3766, 0x04},333 {0x3767, 0x2c},334 {0x3768, 0x02},335 {0x3769, 0x00},336 {0x376b, 0x20},337 {0x376e, 0x03},338 {0x37b0, 0x00},339 {0x37b1, 0xab},340 {0x37b2, 0x01},341 {0x37b3, 0x82},342 {0x37b4, 0x00},343 {0x37b5, 0xe4},344 {0x37b6, 0x01},345 {0x37b7, 0xee},346 {0x3800, 0x00},347 {0x3801, 0x00},348 {0x3802, 0x00},349 {0x3803, 0x00},350 {0x3804, 0x0f},351 {0x3805, 0x1f},352 {0x3806, 0x09},353 {0x3807, 0x7f},354 {0x3808, 0x0f},355 {0x3809, 0x10},356 {0x380a, 0x09},357 {0x380b, 0x70},358 {0x380c, 0x02},359 {0x380d, 0x80},360 {0x380e, 0x13},361 {0x380f, 0x88},362 {0x3810, 0x00},363 {0x3811, 0x08},364 {0x3812, 0x00},365 {0x3813, 0x07},366 {0x3814, 0x11},367 {0x3815, 0x11},368 {0x3820, 0x00},369 {0x3821, 0x04},370 {0x3822, 0x00},371 {0x3823, 0x04},372 {0x3828, 0x0f},373 {0x382a, 0x80},374 {0x382e, 0x41},375 {0x3837, 0x08},376 {0x383a, 0x81},377 {0x383b, 0x81},378 {0x383c, 0x11},379 {0x383d, 0x11},380 {0x383e, 0x00},381 {0x383f, 0x38},382 {0x3840, 0x00},383 {0x3847, 0x00},384 {0x384a, 0x00},385 {0x384c, 0x02},386 {0x384d, 0x80},387 {0x3856, 0x50},388 {0x3857, 0x30},389 {0x3858, 0x80},390 {0x3859, 0x40},391 {0x3860, 0x00},392 {0x3888, 0x00},393 {0x3889, 0x00},394 {0x388a, 0x00},395 {0x388b, 0x00},396 {0x388c, 0x00},397 {0x388d, 0x00},398 {0x388e, 0x00},399 {0x388f, 0x00},400 {0x3894, 0x00},401 {0x3895, 0x00},402 {0x3c84, 0x00},403 {0x3d85, 0x8b},404 {0x3daa, 0x80},405 {0x3dab, 0x14},406 {0x3dac, 0x80},407 {0x3dad, 0xc8},408 {0x3dae, 0x81},409 {0x3daf, 0x7b},410 {0x3f00, 0x10},411 {0x3f01, 0x11},412 {0x3f06, 0x0d},413 {0x3f07, 0x0b},414 {0x3f08, 0x0d},415 {0x3f09, 0x0b},416 {0x3f0a, 0x01},417 {0x3f0b, 0x11},418 {0x3f0c, 0x33},419 {0x4001, 0x07},420 {0x4007, 0x20},421 {0x4008, 0x00},422 {0x4009, 0x05},423 {0x400a, 0x00},424 {0x400b, 0x08},425 {0x400c, 0x00},426 {0x400d, 0x08},427 {0x400e, 0x14},428 {0x4010, 0xf4},429 {0x4011, 0x03},430 {0x4012, 0x55},431 {0x4015, 0x00},432 {0x4016, 0x2d},433 {0x4017, 0x00},434 {0x4018, 0x0f},435 {0x401b, 0x08},436 {0x401c, 0x00},437 {0x401d, 0x10},438 {0x401e, 0x02},439 {0x401f, 0x00},440 {0x4050, 0x06},441 {0x4051, 0xff},442 {0x4052, 0xff},443 {0x4053, 0xff},444 {0x4054, 0xff},445 {0x4055, 0xff},446 {0x4056, 0xff},447 {0x4057, 0x7f},448 {0x4058, 0x00},449 {0x4059, 0x00},450 {0x405a, 0x00},451 {0x405b, 0x00},452 {0x405c, 0x07},453 {0x405d, 0xff},454 {0x405e, 0x07},455 {0x405f, 0xff},456 {0x4080, 0x78},457 {0x4081, 0x78},458 {0x4082, 0x78},459 {0x4083, 0x78},460 {0x4019, 0x00},461 {0x401a, 0x40},462 {0x4020, 0x04},463 {0x4021, 0x00},464 {0x4022, 0x04},465 {0x4023, 0x00},466 {0x4024, 0x04},467 {0x4025, 0x00},468 {0x4026, 0x04},469 {0x4027, 0x00},470 {0x4030, 0x00},471 {0x4031, 0x00},472 {0x4032, 0x00},473 {0x4033, 0x00},474 {0x4034, 0x00},475 {0x4035, 0x00},476 {0x4036, 0x00},477 {0x4037, 0x00},478 {0x4040, 0x00},479 {0x4041, 0x80},480 {0x4042, 0x00},481 {0x4043, 0x80},482 {0x4044, 0x00},483 {0x4045, 0x80},484 {0x4046, 0x00},485 {0x4047, 0x80},486 {0x4060, 0x00},487 {0x4061, 0x00},488 {0x4062, 0x00},489 {0x4063, 0x00},490 {0x4064, 0x00},491 {0x4065, 0x00},492 {0x4066, 0x00},493 {0x4067, 0x00},494 {0x4068, 0x00},495 {0x4069, 0x00},496 {0x406a, 0x00},497 {0x406b, 0x00},498 {0x406c, 0x00},499 {0x406d, 0x00},500 {0x406e, 0x00},501 {0x406f, 0x00},502 {0x4070, 0x00},503 {0x4071, 0x00},504 {0x4072, 0x00},505 {0x4073, 0x00},506 {0x4074, 0x00},507 {0x4075, 0x00},508 {0x4076, 0x00},509 {0x4077, 0x00},510 {0x4078, 0x00},511 {0x4079, 0x00},512 {0x407a, 0x00},513 {0x407b, 0x00},514 {0x407c, 0x00},515 {0x407d, 0x00},516 {0x407e, 0x00},517 {0x407f, 0x00},518 {0x40e0, 0x00},519 {0x40e1, 0x00},520 {0x40e2, 0x00},521 {0x40e3, 0x00},522 {0x40e4, 0x00},523 {0x40e5, 0x00},524 {0x40e6, 0x00},525 {0x40e7, 0x00},526 {0x40e8, 0x00},527 {0x40e9, 0x80},528 {0x40ea, 0x00},529 {0x40eb, 0x80},530 {0x40ec, 0x00},531 {0x40ed, 0x80},532 {0x40ee, 0x00},533 {0x40ef, 0x80},534 {0x40f0, 0x02},535 {0x40f1, 0x04},536 {0x4300, 0x00},537 {0x4301, 0x00},538 {0x4302, 0x00},539 {0x4303, 0x00},540 {0x4304, 0x00},541 {0x4305, 0x00},542 {0x4306, 0x00},543 {0x4307, 0x00},544 {0x4308, 0x00},545 {0x4309, 0x00},546 {0x430a, 0x00},547 {0x430b, 0xff},548 {0x430c, 0xff},549 {0x430d, 0x00},550 {0x430e, 0x00},551 {0x4315, 0x00},552 {0x4316, 0x00},553 {0x4317, 0x00},554 {0x4318, 0x00},555 {0x4319, 0x00},556 {0x431a, 0x00},557 {0x431b, 0x00},558 {0x431c, 0x00},559 {0x4500, 0x07},560 {0x4501, 0x00},561 {0x4502, 0x00},562 {0x4503, 0x0f},563 {0x4504, 0x80},564 {0x4506, 0x01},565 {0x4509, 0x05},566 {0x450c, 0x00},567 {0x450d, 0x20},568 {0x450e, 0x00},569 {0x450f, 0x00},570 {0x4510, 0x00},571 {0x4523, 0x00},572 {0x4526, 0x00},573 {0x4542, 0x00},574 {0x4543, 0x00},575 {0x4544, 0x00},576 {0x4545, 0x00},577 {0x4546, 0x00},578 {0x4547, 0x10},579 {0x4602, 0x00},580 {0x4603, 0x15},581 {0x460b, 0x07},582 {0x4680, 0x11},583 {0x4686, 0x00},584 {0x4687, 0x00},585 {0x4700, 0x00},586 {0x4800, 0x64},587 {0x4806, 0x40},588 {0x480b, 0x10},589 {0x480c, 0x80},590 {0x480f, 0x32},591 {0x4813, 0xe4},592 {0x4837, 0x14},593 {0x4850, 0x42},594 {0x4884, 0x04},595 {0x4c00, 0xf8},596 {0x4c01, 0x44},597 {0x4c03, 0x00},598 {0x4d00, 0x00},599 {0x4d01, 0x16},600 {0x4d04, 0x10},601 {0x4d05, 0x00},602 {0x4d06, 0x0c},603 {0x4d07, 0x00},604 {0x3d84, 0x04},605 {0x3680, 0xa4},606 {0x3682, 0x80},607 {0x3601, 0x40},608 {0x3602, 0x90},609 {0x3608, 0x0a},610 {0x3938, 0x09},611 {0x3a74, 0x84},612 {0x3a99, 0x84},613 {0x3ab9, 0xa6},614 {0x3aba, 0xba},615 {0x3b12, 0x84},616 {0x3b14, 0xbb},617 {0x3b15, 0xbf},618 {0x3a29, 0x26},619 {0x3a1f, 0x8a},620 {0x3a22, 0x91},621 {0x3a25, 0x96},622 {0x3a28, 0xb4},623 {0x3a2b, 0xba},624 {0x3a2e, 0xbf},625 {0x3a31, 0xc1},626 {0x3a20, 0x00},627 {0x3939, 0x9d},628 {0x3902, 0x0e},629 {0x3903, 0x0e},630 {0x3904, 0x0e},631 {0x3905, 0x0e},632 {0x3906, 0x07},633 {0x3907, 0x0d},634 {0x3908, 0x11},635 {0x3909, 0x12},636 {0x360f, 0x99},637 {0x390c, 0x33},638 {0x390d, 0x66},639 {0x390e, 0xaa},640 {0x3911, 0x90},641 {0x3913, 0x90},642 {0x3915, 0x90},643 {0x3917, 0x90},644 {0x3b3f, 0x9d},645 {0x3b45, 0x9d},646 {0x3b1b, 0xc9},647 {0x3b21, 0xc9},648 {0x3440, 0xa4},649 {0x3a23, 0x15},650 {0x3a26, 0x1d},651 {0x3a2c, 0x4a},652 {0x3a2f, 0x18},653 {0x3a32, 0x55},654 {0x3b0a, 0x01},655 {0x3b0b, 0x00},656 {0x3b0e, 0x01},657 {0x3b0f, 0x00},658 {0x392c, 0x02},659 {0x392d, 0x02},660 {0x392e, 0x04},661 {0x392f, 0x03},662 {0x3930, 0x08},663 {0x3931, 0x07},664 {0x3932, 0x10},665 {0x3933, 0x0c},666 {0x3609, 0x08},667 {0x3921, 0x0f},668 {0x3928, 0x15},669 {0x3929, 0x2a},670 {0x392a, 0x54},671 {0x392b, 0xa8},672 {0x3426, 0x10},673 {0x3407, 0x01},674 {0x3404, 0x01},675 {0x3500, 0x00},676 {0x3501, 0x10},677 {0x3502, 0x10},678 {0x3508, 0x0f},679 {0x3509, 0x80},680};681 682static const struct ov08x40_reg mode_1928x1208_regs[] = {683 {0x5000, 0x55},684 {0x5001, 0x00},685 {0x5008, 0xb0},686 {0x50c1, 0x00},687 {0x53c1, 0x00},688 {0x5f40, 0x00},689 {0x5f41, 0x40},690 {0x0300, 0x3a},691 {0x0301, 0xc8},692 {0x0302, 0x31},693 {0x0303, 0x03},694 {0x0304, 0x01},695 {0x0305, 0xa1},696 {0x0306, 0x04},697 {0x0307, 0x01},698 {0x0308, 0x03},699 {0x0309, 0x03},700 {0x0310, 0x0a},701 {0x0311, 0x02},702 {0x0312, 0x01},703 {0x0313, 0x08},704 {0x0314, 0x66},705 {0x0315, 0x00},706 {0x0316, 0x34},707 {0x0320, 0x02},708 {0x0321, 0x03},709 {0x0323, 0x05},710 {0x0324, 0x01},711 {0x0325, 0xb8},712 {0x0326, 0x4a},713 {0x0327, 0x04},714 {0x0329, 0x00},715 {0x032a, 0x05},716 {0x032b, 0x00},717 {0x032c, 0x00},718 {0x032d, 0x00},719 {0x032e, 0x02},720 {0x032f, 0xa0},721 {0x0350, 0x00},722 {0x0360, 0x01},723 {0x1216, 0x60},724 {0x1217, 0x5b},725 {0x1218, 0x00},726 {0x1220, 0x24},727 {0x198a, 0x00},728 {0x198b, 0x01},729 {0x198e, 0x00},730 {0x198f, 0x01},731 {0x3009, 0x04},732 {0x3012, 0x41},733 {0x3015, 0x00},734 {0x3016, 0xb0},735 {0x3017, 0xf0},736 {0x3018, 0xf0},737 {0x3019, 0xd2},738 {0x301a, 0xb0},739 {0x301c, 0x81},740 {0x301d, 0x02},741 {0x301e, 0x80},742 {0x3022, 0xf0},743 {0x3025, 0x89},744 {0x3030, 0x03},745 {0x3044, 0xc2},746 {0x3050, 0x35},747 {0x3051, 0x60},748 {0x3052, 0x25},749 {0x3053, 0x00},750 {0x3054, 0x00},751 {0x3055, 0x02},752 {0x3056, 0x80},753 {0x3057, 0x80},754 {0x3058, 0x80},755 {0x3059, 0x00},756 {0x3107, 0x86},757 {0x3400, 0x1c},758 {0x3401, 0x80},759 {0x3402, 0x8c},760 {0x3419, 0x08},761 {0x341a, 0xaf},762 {0x341b, 0x30},763 {0x3420, 0x00},764 {0x3421, 0x00},765 {0x3422, 0x00},766 {0x3423, 0x00},767 {0x3424, 0x00},768 {0x3425, 0x00},769 {0x3426, 0x00},770 {0x3427, 0x00},771 {0x3428, 0x0f},772 {0x3429, 0x00},773 {0x342a, 0x00},774 {0x342b, 0x00},775 {0x342c, 0x00},776 {0x342d, 0x00},777 {0x342e, 0x00},778 {0x342f, 0x11},779 {0x3430, 0x11},780 {0x3431, 0x10},781 {0x3432, 0x00},782 {0x3433, 0x00},783 {0x3434, 0x00},784 {0x3435, 0x00},785 {0x3436, 0x00},786 {0x3437, 0x00},787 {0x3442, 0x02},788 {0x3443, 0x02},789 {0x3444, 0x07},790 {0x3450, 0x00},791 {0x3451, 0x00},792 {0x3452, 0x18},793 {0x3453, 0x18},794 {0x3454, 0x00},795 {0x3455, 0x80},796 {0x3456, 0x08},797 {0x3500, 0x00},798 {0x3501, 0x02},799 {0x3502, 0x00},800 {0x3504, 0x4c},801 {0x3506, 0x30},802 {0x3507, 0x00},803 {0x3508, 0x01},804 {0x3509, 0x00},805 {0x350a, 0x01},806 {0x350b, 0x00},807 {0x350c, 0x00},808 {0x3540, 0x00},809 {0x3541, 0x01},810 {0x3542, 0x00},811 {0x3544, 0x4c},812 {0x3546, 0x30},813 {0x3547, 0x00},814 {0x3548, 0x01},815 {0x3549, 0x00},816 {0x354a, 0x01},817 {0x354b, 0x00},818 {0x354c, 0x00},819 {0x3688, 0x02},820 {0x368a, 0x2e},821 {0x368e, 0x71},822 {0x3696, 0xd1},823 {0x3699, 0x00},824 {0x369a, 0x00},825 {0x36a4, 0x00},826 {0x36a6, 0x00},827 {0x3711, 0x00},828 {0x3712, 0x50},829 {0x3713, 0x00},830 {0x3714, 0x21},831 {0x3716, 0x00},832 {0x3718, 0x07},833 {0x371a, 0x1c},834 {0x371b, 0x00},835 {0x3720, 0x08},836 {0x3725, 0x32},837 {0x3727, 0x05},838 {0x3760, 0x02},839 {0x3761, 0x28},840 {0x3762, 0x02},841 {0x3763, 0x02},842 {0x3764, 0x02},843 {0x3765, 0x2c},844 {0x3766, 0x04},845 {0x3767, 0x2c},846 {0x3768, 0x02},847 {0x3769, 0x00},848 {0x376b, 0x20},849 {0x376e, 0x07},850 {0x37b0, 0x01},851 {0x37b1, 0x0f},852 {0x37b2, 0x01},853 {0x37b3, 0xd6},854 {0x37b4, 0x01},855 {0x37b5, 0x48},856 {0x37b6, 0x02},857 {0x37b7, 0x40},858 {0x3800, 0x00},859 {0x3801, 0x00},860 {0x3802, 0x00},861 {0x3803, 0x00},862 {0x3804, 0x0f},863 {0x3805, 0x1f},864 {0x3806, 0x09},865 {0x3807, 0x7f},866 {0x3808, 0x07},867 {0x3809, 0x88},868 {0x380a, 0x04},869 {0x380b, 0xb8},870 {0x380c, 0x02},871 {0x380d, 0xd0},872 {0x380e, 0x11},873 {0x380f, 0x5c},874 {0x3810, 0x00},875 {0x3811, 0x04},876 {0x3812, 0x00},877 {0x3813, 0x03},878 {0x3814, 0x11},879 {0x3815, 0x11},880 {0x3820, 0x02},881 {0x3821, 0x14},882 {0x3822, 0x00},883 {0x3823, 0x04},884 {0x3828, 0x0f},885 {0x382a, 0x80},886 {0x382e, 0x41},887 {0x3837, 0x08},888 {0x383a, 0x81},889 {0x383b, 0x81},890 {0x383c, 0x11},891 {0x383d, 0x11},892 {0x383e, 0x00},893 {0x383f, 0x38},894 {0x3840, 0x00},895 {0x3847, 0x00},896 {0x384a, 0x00},897 {0x384c, 0x02},898 {0x384d, 0xd0},899 {0x3856, 0x50},900 {0x3857, 0x30},901 {0x3858, 0x80},902 {0x3859, 0x40},903 {0x3860, 0x00},904 {0x3888, 0x00},905 {0x3889, 0x00},906 {0x388a, 0x00},907 {0x388b, 0x00},908 {0x388c, 0x00},909 {0x388d, 0x00},910 {0x388e, 0x00},911 {0x388f, 0x00},912 {0x3894, 0x00},913 {0x3895, 0x00},914 {0x3c84, 0x00},915 {0x3d85, 0x8b},916 {0x3daa, 0x80},917 {0x3dab, 0x14},918 {0x3dac, 0x80},919 {0x3dad, 0xc8},920 {0x3dae, 0x81},921 {0x3daf, 0x7b},922 {0x3f00, 0x10},923 {0x3f01, 0x11},924 {0x3f06, 0x0d},925 {0x3f07, 0x0b},926 {0x3f08, 0x0d},927 {0x3f09, 0x0b},928 {0x3f0a, 0x01},929 {0x3f0b, 0x11},930 {0x3f0c, 0x33},931 {0x4001, 0x07},932 {0x4007, 0x20},933 {0x4008, 0x00},934 {0x4009, 0x05},935 {0x400a, 0x00},936 {0x400b, 0x04},937 {0x400c, 0x00},938 {0x400d, 0x04},939 {0x400e, 0x14},940 {0x4010, 0xf4},941 {0x4011, 0x03},942 {0x4012, 0x55},943 {0x4015, 0x00},944 {0x4016, 0x27},945 {0x4017, 0x00},946 {0x4018, 0x0f},947 {0x401b, 0x08},948 {0x401c, 0x00},949 {0x401d, 0x10},950 {0x401e, 0x02},951 {0x401f, 0x00},952 {0x4050, 0x06},953 {0x4051, 0xff},954 {0x4052, 0xff},955 {0x4053, 0xff},956 {0x4054, 0xff},957 {0x4055, 0xff},958 {0x4056, 0xff},959 {0x4057, 0x7f},960 {0x4058, 0x00},961 {0x4059, 0x00},962 {0x405a, 0x00},963 {0x405b, 0x00},964 {0x405c, 0x07},965 {0x405d, 0xff},966 {0x405e, 0x07},967 {0x405f, 0xff},968 {0x4080, 0x78},969 {0x4081, 0x78},970 {0x4082, 0x78},971 {0x4083, 0x78},972 {0x4019, 0x00},973 {0x401a, 0x40},974 {0x4020, 0x04},975 {0x4021, 0x00},976 {0x4022, 0x04},977 {0x4023, 0x00},978 {0x4024, 0x04},979 {0x4025, 0x00},980 {0x4026, 0x04},981 {0x4027, 0x00},982 {0x4030, 0x00},983 {0x4031, 0x00},984 {0x4032, 0x00},985 {0x4033, 0x00},986 {0x4034, 0x00},987 {0x4035, 0x00},988 {0x4036, 0x00},989 {0x4037, 0x00},990 {0x4040, 0x00},991 {0x4041, 0x80},992 {0x4042, 0x00},993 {0x4043, 0x80},994 {0x4044, 0x00},995 {0x4045, 0x80},996 {0x4046, 0x00},997 {0x4047, 0x80},998 {0x4060, 0x00},999 {0x4061, 0x00},1000 {0x4062, 0x00},1001 {0x4063, 0x00},1002 {0x4064, 0x00},1003 {0x4065, 0x00},1004 {0x4066, 0x00},1005 {0x4067, 0x00},1006 {0x4068, 0x00},1007 {0x4069, 0x00},1008 {0x406a, 0x00},1009 {0x406b, 0x00},1010 {0x406c, 0x00},1011 {0x406d, 0x00},1012 {0x406e, 0x00},1013 {0x406f, 0x00},1014 {0x4070, 0x00},1015 {0x4071, 0x00},1016 {0x4072, 0x00},1017 {0x4073, 0x00},1018 {0x4074, 0x00},1019 {0x4075, 0x00},1020 {0x4076, 0x00},1021 {0x4077, 0x00},1022 {0x4078, 0x00},1023 {0x4079, 0x00},1024 {0x407a, 0x00},1025 {0x407b, 0x00},1026 {0x407c, 0x00},1027 {0x407d, 0x00},1028 {0x407e, 0x00},1029 {0x407f, 0x00},1030 {0x40e0, 0x00},1031 {0x40e1, 0x00},1032 {0x40e2, 0x00},1033 {0x40e3, 0x00},1034 {0x40e4, 0x00},1035 {0x40e5, 0x00},1036 {0x40e6, 0x00},1037 {0x40e7, 0x00},1038 {0x40e8, 0x00},1039 {0x40e9, 0x80},1040 {0x40ea, 0x00},1041 {0x40eb, 0x80},1042 {0x40ec, 0x00},1043 {0x40ed, 0x80},1044 {0x40ee, 0x00},1045 {0x40ef, 0x80},1046 {0x40f0, 0x02},1047 {0x40f1, 0x04},1048 {0x4300, 0x00},1049 {0x4301, 0x00},1050 {0x4302, 0x00},1051 {0x4303, 0x00},1052 {0x4304, 0x00},1053 {0x4305, 0x00},1054 {0x4306, 0x00},1055 {0x4307, 0x00},1056 {0x4308, 0x00},1057 {0x4309, 0x00},1058 {0x430a, 0x00},1059 {0x430b, 0xff},1060 {0x430c, 0xff},1061 {0x430d, 0x00},1062 {0x430e, 0x00},1063 {0x4315, 0x00},1064 {0x4316, 0x00},1065 {0x4317, 0x00},1066 {0x4318, 0x00},1067 {0x4319, 0x00},1068 {0x431a, 0x00},1069 {0x431b, 0x00},1070 {0x431c, 0x00},1071 {0x4500, 0x07},1072 {0x4501, 0x10},1073 {0x4502, 0x00},1074 {0x4503, 0x0f},1075 {0x4504, 0x80},1076 {0x4506, 0x01},1077 {0x4509, 0x05},1078 {0x450c, 0x00},1079 {0x450d, 0x20},1080 {0x450e, 0x00},1081 {0x450f, 0x00},1082 {0x4510, 0x00},1083 {0x4523, 0x00},1084 {0x4526, 0x00},1085 {0x4542, 0x00},1086 {0x4543, 0x00},1087 {0x4544, 0x00},1088 {0x4545, 0x00},1089 {0x4546, 0x00},1090 {0x4547, 0x10},1091 {0x4602, 0x00},1092 {0x4603, 0x15},1093 {0x460b, 0x07},1094 {0x4680, 0x11},1095 {0x4686, 0x00},1096 {0x4687, 0x00},1097 {0x4700, 0x00},1098 {0x4800, 0x64},1099 {0x4806, 0x40},1100 {0x480b, 0x10},1101 {0x480c, 0x80},1102 {0x480f, 0x32},1103 {0x4813, 0xe4},1104 {0x4837, 0x14},1105 {0x4850, 0x42},1106 {0x4884, 0x04},1107 {0x4c00, 0xf8},1108 {0x4c01, 0x44},1109 {0x4c03, 0x00},1110 {0x4d00, 0x00},1111 {0x4d01, 0x16},1112 {0x4d04, 0x10},1113 {0x4d05, 0x00},1114 {0x4d06, 0x0c},1115 {0x4d07, 0x00},1116 {0x3d84, 0x04},1117 {0x3680, 0xa4},1118 {0x3682, 0x80},1119 {0x3601, 0x40},1120 {0x3602, 0x90},1121 {0x3608, 0x0a},1122 {0x3938, 0x09},1123 {0x3a74, 0x84},1124 {0x3a99, 0x84},1125 {0x3ab9, 0xa6},1126 {0x3aba, 0xba},1127 {0x3b12, 0x84},1128 {0x3b14, 0xbb},1129 {0x3b15, 0xbf},1130 {0x3a29, 0x26},1131 {0x3a1f, 0x8a},1132 {0x3a22, 0x91},1133 {0x3a25, 0x96},1134 {0x3a28, 0xb4},1135 {0x3a2b, 0xba},1136 {0x3a2e, 0xbf},1137 {0x3a31, 0xc1},1138 {0x3a20, 0x05},1139 {0x3939, 0x6b},1140 {0x3902, 0x10},1141 {0x3903, 0x10},1142 {0x3904, 0x10},1143 {0x3905, 0x10},1144 {0x3906, 0x01},1145 {0x3907, 0x0b},1146 {0x3908, 0x10},1147 {0x3909, 0x13},1148 {0x360f, 0x99},1149 {0x390b, 0x11},1150 {0x390c, 0x21},1151 {0x390d, 0x32},1152 {0x390e, 0x76},1153 {0x3911, 0x90},1154 {0x3913, 0x90},1155 {0x3b3f, 0x9d},1156 {0x3b45, 0x9d},1157 {0x3b1b, 0xc9},1158 {0x3b21, 0xc9},1159 {0x3a1a, 0x1c},1160 {0x3a23, 0x15},1161 {0x3a26, 0x17},1162 {0x3a2c, 0x50},1163 {0x3a2f, 0x18},1164 {0x3a32, 0x4f},1165 {0x3ace, 0x01},1166 {0x3ad2, 0x01},1167 {0x3ad6, 0x01},1168 {0x3ada, 0x01},1169 {0x3ade, 0x01},1170 {0x3ae2, 0x01},1171 {0x3aee, 0x01},1172 {0x3af2, 0x01},1173 {0x3af6, 0x01},1174 {0x3afa, 0x01},1175 {0x3afe, 0x01},1176 {0x3b02, 0x01},1177 {0x3b06, 0x01},1178 {0x3b0a, 0x01},1179 {0x3b0b, 0x00},1180 {0x3b0e, 0x01},1181 {0x3b0f, 0x00},1182 {0x392c, 0x02},1183 {0x392d, 0x01},1184 {0x392e, 0x04},1185 {0x392f, 0x03},1186 {0x3930, 0x09},1187 {0x3931, 0x07},1188 {0x3932, 0x10},1189 {0x3933, 0x0d},1190 {0x3609, 0x08},1191 {0x3921, 0x0f},1192 {0x3928, 0x15},1193 {0x3929, 0x2a},1194 {0x392a, 0x52},1195 {0x392b, 0xa3},1196 {0x340b, 0x1b},1197 {0x3426, 0x10},1198 {0x3407, 0x01},1199 {0x3404, 0x01},1200 {0x3500, 0x00},1201 {0x3501, 0x08},1202 {0x3502, 0x10},1203 {0x3508, 0x04},1204 {0x3509, 0x00},1205};1206 1207static const char * const ov08x40_test_pattern_menu[] = {1208 "Disabled",1209 "Vertical Color Bar Type 1",1210 "Vertical Color Bar Type 2",1211 "Vertical Color Bar Type 3",1212 "Vertical Color Bar Type 4"1213};1214 1215/* Configurations for supported link frequencies */1216#define OV08X40_LINK_FREQ_400MHZ 400000000ULL1217#define OV08X40_SCLK_96MHZ 96000000ULL1218#define OV08X40_EXT_CLK 192000001219#define OV08X40_DATA_LANES 41220 1221/*1222 * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample1223 * data rate => double data rate; number of lanes => 4; bits per pixel => 101224 */1225static u64 link_freq_to_pixel_rate(u64 f)1226{1227 f *= 2 * OV08X40_DATA_LANES;1228 do_div(f, 10);1229 1230 return f;1231}1232 1233/* Menu items for LINK_FREQ V4L2 control */1234static const s64 link_freq_menu_items[] = {1235 OV08X40_LINK_FREQ_400MHZ,1236};1237 1238/* Link frequency configs */1239static const struct ov08x40_link_freq_config link_freq_configs[] = {1240 [OV08X40_LINK_FREQ_400MHZ_INDEX] = {1241 .reg_list = {1242 .num_of_regs = ARRAY_SIZE(mipi_data_rate_800mbps),1243 .regs = mipi_data_rate_800mbps,1244 }1245 },1246};1247 1248/* Mode configs */1249static const struct ov08x40_mode supported_modes[] = {1250 {1251 .width = 3856,1252 .height = 2416,1253 .vts_def = OV08X40_VTS_30FPS,1254 .vts_min = OV08X40_VTS_30FPS,1255 .llp = 0x10aa, /* in normal mode, tline time = 2 * HTS / SCLK */1256 .lanes = 4,1257 .reg_list = {1258 .num_of_regs = ARRAY_SIZE(mode_3856x2416_regs),1259 .regs = mode_3856x2416_regs,1260 },1261 .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,1262 .exposure_shift = 1,1263 .exposure_margin = OV08X40_EXPOSURE_MAX_MARGIN,1264 },1265 {1266 .width = 1928,1267 .height = 1208,1268 .vts_def = OV08X40_VTS_BIN_30FPS,1269 .vts_min = OV08X40_VTS_BIN_30FPS,1270 .llp = 0x960,1271 .lanes = 4,1272 .reg_list = {1273 .num_of_regs = ARRAY_SIZE(mode_1928x1208_regs),1274 .regs = mode_1928x1208_regs,1275 },1276 .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,1277 .exposure_shift = 0,1278 .exposure_margin = OV08X40_EXPOSURE_BIN_MAX_MARGIN,1279 },1280};1281 1282struct ov08x40 {1283 struct v4l2_subdev sd;1284 struct media_pad pad;1285 1286 struct v4l2_ctrl_handler ctrl_handler;1287 /* V4L2 Controls */1288 struct v4l2_ctrl *link_freq;1289 struct v4l2_ctrl *pixel_rate;1290 struct v4l2_ctrl *vblank;1291 struct v4l2_ctrl *hblank;1292 struct v4l2_ctrl *exposure;1293 1294 /* Current mode */1295 const struct ov08x40_mode *cur_mode;1296 1297 /* Mutex for serialized access */1298 struct mutex mutex;1299 1300 /* True if the device has been identified */1301 bool identified;1302};1303 1304#define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd)1305 1306/* Read registers up to 4 at a time */1307static int ov08x40_read_reg(struct ov08x40 *ov08x,1308 u16 reg, u32 len, u32 *val)1309{1310 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1311 struct i2c_msg msgs[2];1312 u8 *data_be_p;1313 int ret;1314 __be32 data_be = 0;1315 __be16 reg_addr_be = cpu_to_be16(reg);1316 1317 if (len > 4)1318 return -EINVAL;1319 1320 data_be_p = (u8 *)&data_be;1321 /* Write register address */1322 msgs[0].addr = client->addr;1323 msgs[0].flags = 0;1324 msgs[0].len = 2;1325 msgs[0].buf = (u8 *)®_addr_be;1326 1327 /* Read data from register */1328 msgs[1].addr = client->addr;1329 msgs[1].flags = I2C_M_RD;1330 msgs[1].len = len;1331 msgs[1].buf = &data_be_p[4 - len];1332 1333 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));1334 if (ret != ARRAY_SIZE(msgs))1335 return -EIO;1336 1337 *val = be32_to_cpu(data_be);1338 1339 return 0;1340}1341 1342static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,1343 u16 last_reg, u8 val)1344{1345 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1346 struct i2c_msg msgs;1347 size_t i, num_regs;1348 int ret;1349 1350 num_regs = last_reg - first_reg + 1;1351 msgs.addr = client->addr;1352 msgs.flags = 0;1353 msgs.len = 2 + num_regs;1354 msgs.buf = kmalloc(msgs.len, GFP_KERNEL);1355 1356 if (!msgs.buf)1357 return -ENOMEM;1358 1359 put_unaligned_be16(first_reg, msgs.buf);1360 1361 for (i = 0; i < num_regs; ++i)1362 msgs.buf[2 + i] = val;1363 1364 ret = i2c_transfer(client->adapter, &msgs, 1);1365 1366 kfree(msgs.buf);1367 1368 if (ret != 1) {1369 dev_err(&client->dev, "Failed regs transferred: %d\n", ret);1370 return -EIO;1371 }1372 1373 return 0;1374}1375 1376/* Write registers up to 4 at a time */1377static int ov08x40_write_reg(struct ov08x40 *ov08x,1378 u16 reg, u32 len, u32 __val)1379{1380 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1381 int buf_i, val_i;1382 u8 buf[6], *val_p;1383 __be32 val;1384 1385 if (len > 4)1386 return -EINVAL;1387 1388 buf[0] = reg >> 8;1389 buf[1] = reg & 0xff;1390 1391 val = cpu_to_be32(__val);1392 val_p = (u8 *)&val;1393 buf_i = 2;1394 val_i = 4 - len;1395 1396 while (val_i < 4)1397 buf[buf_i++] = val_p[val_i++];1398 1399 if (i2c_master_send(client, buf, len + 2) != len + 2)1400 return -EIO;1401 1402 return 0;1403}1404 1405/* Write a list of registers */1406static int ov08x40_write_regs(struct ov08x40 *ov08x,1407 const struct ov08x40_reg *regs, u32 len)1408{1409 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1410 int ret;1411 u32 i;1412 1413 for (i = 0; i < len; i++) {1414 ret = ov08x40_write_reg(ov08x, regs[i].address, 1,1415 regs[i].val);1416 1417 if (ret) {1418 dev_err_ratelimited(&client->dev,1419 "Failed to write reg 0x%4.4x. error = %d\n",1420 regs[i].address, ret);1421 1422 return ret;1423 }1424 }1425 1426 return 0;1427}1428 1429static int ov08x40_write_reg_list(struct ov08x40 *ov08x,1430 const struct ov08x40_reg_list *r_list)1431{1432 return ov08x40_write_regs(ov08x, r_list->regs, r_list->num_of_regs);1433}1434 1435static int ov08x40_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1436{1437 const struct ov08x40_mode *default_mode = &supported_modes[0];1438 struct ov08x40 *ov08x = to_ov08x40(sd);1439 struct v4l2_mbus_framefmt *try_fmt =1440 v4l2_subdev_state_get_format(fh->state, 0);1441 1442 mutex_lock(&ov08x->mutex);1443 1444 /* Initialize try_fmt */1445 try_fmt->width = default_mode->width;1446 try_fmt->height = default_mode->height;1447 try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;1448 try_fmt->field = V4L2_FIELD_NONE;1449 1450 /* No crop or compose */1451 mutex_unlock(&ov08x->mutex);1452 1453 return 0;1454}1455 1456static int ov08x40_update_digital_gain(struct ov08x40 *ov08x, u32 d_gain)1457{1458 int ret;1459 u32 val;1460 1461 /*1462 * 0x350C[1:0], 0x350B[7:0], 0x350A[4:0]1463 */1464 1465 val = (d_gain & OV08X40_DGTL_GAIN_L_MASK) << OV08X40_DGTL_GAIN_L_SHIFT;1466 ret = ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_L,1467 OV08X40_REG_VALUE_08BIT, val);1468 if (ret)1469 return ret;1470 1471 val = (d_gain >> OV08X40_DGTL_GAIN_M_SHIFT) & OV08X40_DGTL_GAIN_M_MASK;1472 ret = ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_M,1473 OV08X40_REG_VALUE_08BIT, val);1474 if (ret)1475 return ret;1476 1477 val = (d_gain >> OV08X40_DGTL_GAIN_H_SHIFT) & OV08X40_DGTL_GAIN_H_MASK;1478 1479 return ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_H,1480 OV08X40_REG_VALUE_08BIT, val);1481}1482 1483static int ov08x40_enable_test_pattern(struct ov08x40 *ov08x, u32 pattern)1484{1485 int ret;1486 u32 val;1487 1488 ret = ov08x40_read_reg(ov08x, OV08X40_REG_TEST_PATTERN,1489 OV08X40_REG_VALUE_08BIT, &val);1490 if (ret)1491 return ret;1492 1493 if (pattern) {1494 ret = ov08x40_read_reg(ov08x, OV08X40_REG_ISP,1495 OV08X40_REG_VALUE_08BIT, &val);1496 if (ret)1497 return ret;1498 1499 ret = ov08x40_write_reg(ov08x, OV08X40_REG_ISP,1500 OV08X40_REG_VALUE_08BIT,1501 val | BIT(1));1502 if (ret)1503 return ret;1504 1505 ret = ov08x40_read_reg(ov08x, OV08X40_REG_SHORT_TEST_PATTERN,1506 OV08X40_REG_VALUE_08BIT, &val);1507 if (ret)1508 return ret;1509 1510 ret = ov08x40_write_reg(ov08x, OV08X40_REG_SHORT_TEST_PATTERN,1511 OV08X40_REG_VALUE_08BIT,1512 val | BIT(0));1513 if (ret)1514 return ret;1515 1516 ret = ov08x40_read_reg(ov08x, OV08X40_REG_TEST_PATTERN,1517 OV08X40_REG_VALUE_08BIT, &val);1518 if (ret)1519 return ret;1520 1521 val &= OV08X40_TEST_PATTERN_MASK;1522 val |= ((pattern - 1) << OV08X40_TEST_PATTERN_BAR_SHIFT) |1523 OV08X40_TEST_PATTERN_ENABLE;1524 } else {1525 val &= ~OV08X40_TEST_PATTERN_ENABLE;1526 }1527 1528 return ov08x40_write_reg(ov08x, OV08X40_REG_TEST_PATTERN,1529 OV08X40_REG_VALUE_08BIT, val);1530}1531 1532static int ov08x40_set_ctrl_hflip(struct ov08x40 *ov08x, u32 ctrl_val)1533{1534 int ret;1535 u32 val;1536 1537 ret = ov08x40_read_reg(ov08x, OV08X40_REG_MIRROR,1538 OV08X40_REG_VALUE_08BIT, &val);1539 if (ret)1540 return ret;1541 1542 return ov08x40_write_reg(ov08x, OV08X40_REG_MIRROR,1543 OV08X40_REG_VALUE_08BIT,1544 ctrl_val ? val | BIT(2) : val & ~BIT(2));1545}1546 1547static int ov08x40_set_ctrl_vflip(struct ov08x40 *ov08x, u32 ctrl_val)1548{1549 int ret;1550 u32 val;1551 1552 ret = ov08x40_read_reg(ov08x, OV08X40_REG_VFLIP,1553 OV08X40_REG_VALUE_08BIT, &val);1554 if (ret)1555 return ret;1556 1557 return ov08x40_write_reg(ov08x, OV08X40_REG_VFLIP,1558 OV08X40_REG_VALUE_08BIT,1559 ctrl_val ? val | BIT(2) : val & ~BIT(2));1560}1561 1562static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl)1563{1564 struct ov08x40 *ov08x = container_of(ctrl->handler,1565 struct ov08x40, ctrl_handler);1566 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1567 s64 max;1568 int exp;1569 int fll;1570 int ret = 0;1571 1572 /* Propagate change of current control to all related controls */1573 switch (ctrl->id) {1574 case V4L2_CID_VBLANK:1575 /* Update max exposure while meeting expected vblanking */1576 /*1577 * because in normal mode, 1 HTS = 0.5 tline1578 * fps = sclk / hts / vts1579 * so the vts value needs to be double1580 */1581 max = ((ov08x->cur_mode->height + ctrl->val) <<1582 ov08x->cur_mode->exposure_shift) -1583 ov08x->cur_mode->exposure_margin;1584 1585 __v4l2_ctrl_modify_range(ov08x->exposure,1586 ov08x->exposure->minimum,1587 max, ov08x->exposure->step, max);1588 break;1589 }1590 1591 /*1592 * Applying V4L2 control value only happens1593 * when power is up for streaming1594 */1595 if (!pm_runtime_get_if_in_use(&client->dev))1596 return 0;1597 1598 switch (ctrl->id) {1599 case V4L2_CID_ANALOGUE_GAIN:1600 ret = ov08x40_write_reg(ov08x, OV08X40_REG_ANALOG_GAIN,1601 OV08X40_REG_VALUE_16BIT,1602 ctrl->val << 1);1603 break;1604 case V4L2_CID_DIGITAL_GAIN:1605 ret = ov08x40_update_digital_gain(ov08x, ctrl->val);1606 break;1607 case V4L2_CID_EXPOSURE:1608 exp = (ctrl->val << ov08x->cur_mode->exposure_shift) -1609 ov08x->cur_mode->exposure_margin;1610 1611 ret = ov08x40_write_reg(ov08x, OV08X40_REG_EXPOSURE,1612 OV08X40_REG_VALUE_24BIT,1613 exp);1614 break;1615 case V4L2_CID_VBLANK:1616 fll = ((ov08x->cur_mode->height + ctrl->val) <<1617 ov08x->cur_mode->exposure_shift);1618 1619 ret = ov08x40_write_reg(ov08x, OV08X40_REG_VTS,1620 OV08X40_REG_VALUE_16BIT,1621 fll);1622 break;1623 case V4L2_CID_TEST_PATTERN:1624 ret = ov08x40_enable_test_pattern(ov08x, ctrl->val);1625 break;1626 case V4L2_CID_HFLIP:1627 ov08x40_set_ctrl_hflip(ov08x, ctrl->val);1628 break;1629 case V4L2_CID_VFLIP:1630 ov08x40_set_ctrl_vflip(ov08x, ctrl->val);1631 break;1632 default:1633 dev_info(&client->dev,1634 "ctrl(id:0x%x,val:0x%x) is not handled\n",1635 ctrl->id, ctrl->val);1636 break;1637 }1638 1639 pm_runtime_put(&client->dev);1640 1641 return ret;1642}1643 1644static const struct v4l2_ctrl_ops ov08x40_ctrl_ops = {1645 .s_ctrl = ov08x40_set_ctrl,1646};1647 1648static int ov08x40_enum_mbus_code(struct v4l2_subdev *sd,1649 struct v4l2_subdev_state *sd_state,1650 struct v4l2_subdev_mbus_code_enum *code)1651{1652 /* Only one bayer order(GRBG) is supported */1653 if (code->index > 0)1654 return -EINVAL;1655 1656 code->code = MEDIA_BUS_FMT_SGRBG10_1X10;1657 1658 return 0;1659}1660 1661static int ov08x40_enum_frame_size(struct v4l2_subdev *sd,1662 struct v4l2_subdev_state *sd_state,1663 struct v4l2_subdev_frame_size_enum *fse)1664{1665 if (fse->index >= ARRAY_SIZE(supported_modes))1666 return -EINVAL;1667 1668 if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)1669 return -EINVAL;1670 1671 fse->min_width = supported_modes[fse->index].width;1672 fse->max_width = fse->min_width;1673 fse->min_height = supported_modes[fse->index].height;1674 fse->max_height = fse->min_height;1675 1676 return 0;1677}1678 1679static void ov08x40_update_pad_format(const struct ov08x40_mode *mode,1680 struct v4l2_subdev_format *fmt)1681{1682 fmt->format.width = mode->width;1683 fmt->format.height = mode->height;1684 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;1685 fmt->format.field = V4L2_FIELD_NONE;1686}1687 1688static int ov08x40_do_get_pad_format(struct ov08x40 *ov08x,1689 struct v4l2_subdev_state *sd_state,1690 struct v4l2_subdev_format *fmt)1691{1692 struct v4l2_mbus_framefmt *framefmt;1693 1694 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1695 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);1696 fmt->format = *framefmt;1697 } else {1698 ov08x40_update_pad_format(ov08x->cur_mode, fmt);1699 }1700 1701 return 0;1702}1703 1704static int ov08x40_get_pad_format(struct v4l2_subdev *sd,1705 struct v4l2_subdev_state *sd_state,1706 struct v4l2_subdev_format *fmt)1707{1708 struct ov08x40 *ov08x = to_ov08x40(sd);1709 int ret;1710 1711 mutex_lock(&ov08x->mutex);1712 ret = ov08x40_do_get_pad_format(ov08x, sd_state, fmt);1713 mutex_unlock(&ov08x->mutex);1714 1715 return ret;1716}1717 1718static int1719ov08x40_set_pad_format(struct v4l2_subdev *sd,1720 struct v4l2_subdev_state *sd_state,1721 struct v4l2_subdev_format *fmt)1722{1723 struct ov08x40 *ov08x = to_ov08x40(sd);1724 const struct ov08x40_mode *mode;1725 struct v4l2_mbus_framefmt *framefmt;1726 s32 vblank_def;1727 s32 vblank_min;1728 s64 h_blank;1729 s64 pixel_rate;1730 s64 link_freq;1731 u64 steps;1732 1733 mutex_lock(&ov08x->mutex);1734 1735 /* Only one raw bayer(GRBG) order is supported */1736 if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10)1737 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;1738 1739 mode = v4l2_find_nearest_size(supported_modes,1740 ARRAY_SIZE(supported_modes),1741 width, height,1742 fmt->format.width, fmt->format.height);1743 ov08x40_update_pad_format(mode, fmt);1744 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1745 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);1746 *framefmt = fmt->format;1747 } else {1748 ov08x->cur_mode = mode;1749 __v4l2_ctrl_s_ctrl(ov08x->link_freq, mode->link_freq_index);1750 link_freq = link_freq_menu_items[mode->link_freq_index];1751 pixel_rate = link_freq_to_pixel_rate(link_freq);1752 __v4l2_ctrl_s_ctrl_int64(ov08x->pixel_rate, pixel_rate);1753 1754 /* Update limits and set FPS to default */1755 vblank_def = ov08x->cur_mode->vts_def -1756 ov08x->cur_mode->height;1757 vblank_min = ov08x->cur_mode->vts_min -1758 ov08x->cur_mode->height;1759 1760 /*1761 * The frame length line should be aligned to a multiple of 4,1762 * as provided by the sensor vendor, in normal mode.1763 */1764 steps = mode->exposure_shift == 1 ? 4 : 1;1765 1766 __v4l2_ctrl_modify_range(ov08x->vblank, vblank_min,1767 OV08X40_VTS_MAX1768 - ov08x->cur_mode->height,1769 steps,1770 vblank_def);1771 __v4l2_ctrl_s_ctrl(ov08x->vblank, vblank_def);1772 1773 h_blank = ov08x->cur_mode->llp - ov08x->cur_mode->width;1774 1775 __v4l2_ctrl_modify_range(ov08x->hblank, h_blank,1776 h_blank, 1, h_blank);1777 }1778 1779 mutex_unlock(&ov08x->mutex);1780 1781 return 0;1782}1783 1784static int ov08x40_start_streaming(struct ov08x40 *ov08x)1785{1786 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1787 const struct ov08x40_reg_list *reg_list;1788 int ret, link_freq_index;1789 1790 /* Get out of from software reset */1791 ret = ov08x40_write_reg(ov08x, OV08X40_REG_SOFTWARE_RST,1792 OV08X40_REG_VALUE_08BIT, OV08X40_SOFTWARE_RST);1793 if (ret) {1794 dev_err(&client->dev, "%s failed to set powerup registers\n",1795 __func__);1796 return ret;1797 }1798 1799 link_freq_index = ov08x->cur_mode->link_freq_index;1800 reg_list = &link_freq_configs[link_freq_index].reg_list;1801 1802 ret = ov08x40_write_reg_list(ov08x, reg_list);1803 if (ret) {1804 dev_err(&client->dev, "%s failed to set plls\n", __func__);1805 return ret;1806 }1807 1808 /* Apply default values of current mode */1809 reg_list = &ov08x->cur_mode->reg_list;1810 ret = ov08x40_write_reg_list(ov08x, reg_list);1811 if (ret) {1812 dev_err(&client->dev, "%s failed to set mode\n", __func__);1813 return ret;1814 }1815 1816 /* Use i2c burst to write register on full size registers */1817 if (ov08x->cur_mode->exposure_shift == 1) {1818 ret = ov08x40_burst_fill_regs(ov08x, OV08X40_REG_XTALK_FIRST_A,1819 OV08X40_REG_XTALK_LAST_A, 0x75);1820 if (ret == 0)1821 ret = ov08x40_burst_fill_regs(ov08x,1822 OV08X40_REG_XTALK_FIRST_B,1823 OV08X40_REG_XTALK_LAST_B,1824 0x75);1825 }1826 1827 if (ret) {1828 dev_err(&client->dev, "%s failed to set regs\n", __func__);1829 return ret;1830 }1831 1832 /* Apply customized values from user */1833 ret = __v4l2_ctrl_handler_setup(ov08x->sd.ctrl_handler);1834 if (ret)1835 return ret;1836 1837 return ov08x40_write_reg(ov08x, OV08X40_REG_MODE_SELECT,1838 OV08X40_REG_VALUE_08BIT,1839 OV08X40_MODE_STREAMING);1840}1841 1842/* Stop streaming */1843static int ov08x40_stop_streaming(struct ov08x40 *ov08x)1844{1845 return ov08x40_write_reg(ov08x, OV08X40_REG_MODE_SELECT,1846 OV08X40_REG_VALUE_08BIT, OV08X40_MODE_STANDBY);1847}1848 1849static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable)1850{1851 struct ov08x40 *ov08x = to_ov08x40(sd);1852 struct i2c_client *client = v4l2_get_subdevdata(sd);1853 int ret = 0;1854 1855 mutex_lock(&ov08x->mutex);1856 1857 if (enable) {1858 ret = pm_runtime_resume_and_get(&client->dev);1859 if (ret < 0)1860 goto err_unlock;1861 1862 /*1863 * Apply default & customized values1864 * and then start streaming.1865 */1866 ret = ov08x40_start_streaming(ov08x);1867 if (ret)1868 goto err_rpm_put;1869 } else {1870 ov08x40_stop_streaming(ov08x);1871 pm_runtime_put(&client->dev);1872 }1873 1874 mutex_unlock(&ov08x->mutex);1875 1876 return ret;1877 1878err_rpm_put:1879 pm_runtime_put(&client->dev);1880err_unlock:1881 mutex_unlock(&ov08x->mutex);1882 1883 return ret;1884}1885 1886/* Verify chip ID */1887static int ov08x40_identify_module(struct ov08x40 *ov08x)1888{1889 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1890 int ret;1891 u32 val;1892 1893 if (ov08x->identified)1894 return 0;1895 1896 ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID,1897 OV08X40_REG_VALUE_24BIT, &val);1898 if (ret)1899 return ret;1900 1901 if (val != OV08X40_CHIP_ID) {1902 dev_err(&client->dev, "chip id mismatch: %x!=%x\n",1903 OV08X40_CHIP_ID, val);1904 return -ENXIO;1905 }1906 1907 ov08x->identified = true;1908 1909 return 0;1910}1911 1912static const struct v4l2_subdev_video_ops ov08x40_video_ops = {1913 .s_stream = ov08x40_set_stream,1914};1915 1916static const struct v4l2_subdev_pad_ops ov08x40_pad_ops = {1917 .enum_mbus_code = ov08x40_enum_mbus_code,1918 .get_fmt = ov08x40_get_pad_format,1919 .set_fmt = ov08x40_set_pad_format,1920 .enum_frame_size = ov08x40_enum_frame_size,1921};1922 1923static const struct v4l2_subdev_ops ov08x40_subdev_ops = {1924 .video = &ov08x40_video_ops,1925 .pad = &ov08x40_pad_ops,1926};1927 1928static const struct media_entity_operations ov08x40_subdev_entity_ops = {1929 .link_validate = v4l2_subdev_link_validate,1930};1931 1932static const struct v4l2_subdev_internal_ops ov08x40_internal_ops = {1933 .open = ov08x40_open,1934};1935 1936static int ov08x40_init_controls(struct ov08x40 *ov08x)1937{1938 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);1939 struct v4l2_fwnode_device_properties props;1940 struct v4l2_ctrl_handler *ctrl_hdlr;1941 s64 exposure_max;1942 s64 vblank_def;1943 s64 vblank_min;1944 s64 hblank;1945 s64 pixel_rate_min;1946 s64 pixel_rate_max;1947 const struct ov08x40_mode *mode;1948 u32 max;1949 int ret;1950 1951 ctrl_hdlr = &ov08x->ctrl_handler;1952 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);1953 if (ret)1954 return ret;1955 1956 mutex_init(&ov08x->mutex);1957 ctrl_hdlr->lock = &ov08x->mutex;1958 max = ARRAY_SIZE(link_freq_menu_items) - 1;1959 ov08x->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,1960 &ov08x40_ctrl_ops,1961 V4L2_CID_LINK_FREQ,1962 max,1963 0,1964 link_freq_menu_items);1965 if (ov08x->link_freq)1966 ov08x->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;1967 1968 pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);1969 pixel_rate_min = 0;1970 /* By default, PIXEL_RATE is read only */1971 ov08x->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,1972 V4L2_CID_PIXEL_RATE,1973 pixel_rate_min, pixel_rate_max,1974 1, pixel_rate_max);1975 1976 mode = ov08x->cur_mode;1977 vblank_def = mode->vts_def - mode->height;1978 vblank_min = mode->vts_min - mode->height;1979 ov08x->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,1980 V4L2_CID_VBLANK,1981 vblank_min,1982 OV08X40_VTS_MAX - mode->height, 1,1983 vblank_def);1984 1985 hblank = ov08x->cur_mode->llp - ov08x->cur_mode->width;1986 1987 ov08x->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,1988 V4L2_CID_HBLANK,1989 hblank, hblank, 1, hblank);1990 if (ov08x->hblank)1991 ov08x->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;1992 1993 exposure_max = mode->vts_def - OV08X40_EXPOSURE_MAX_MARGIN;1994 ov08x->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,1995 V4L2_CID_EXPOSURE,1996 OV08X40_EXPOSURE_MIN,1997 exposure_max, OV08X40_EXPOSURE_STEP,1998 exposure_max);1999 2000 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,2001 OV08X40_ANA_GAIN_MIN, OV08X40_ANA_GAIN_MAX,2002 OV08X40_ANA_GAIN_STEP, OV08X40_ANA_GAIN_DEFAULT);2003 2004 /* Digital gain */2005 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops, V4L2_CID_DIGITAL_GAIN,2006 OV08X40_DGTL_GAIN_MIN, OV08X40_DGTL_GAIN_MAX,2007 OV08X40_DGTL_GAIN_STEP, OV08X40_DGTL_GAIN_DEFAULT);2008 2009 v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov08x40_ctrl_ops,2010 V4L2_CID_TEST_PATTERN,2011 ARRAY_SIZE(ov08x40_test_pattern_menu) - 1,2012 0, 0, ov08x40_test_pattern_menu);2013 2014 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,2015 V4L2_CID_HFLIP, 0, 1, 1, 0);2016 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,2017 V4L2_CID_VFLIP, 0, 1, 1, 0);2018 2019 if (ctrl_hdlr->error) {2020 ret = ctrl_hdlr->error;2021 dev_err(&client->dev, "%s control init failed (%d)\n",2022 __func__, ret);2023 goto error;2024 }2025 2026 ret = v4l2_fwnode_device_parse(&client->dev, &props);2027 if (ret)2028 goto error;2029 2030 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov08x40_ctrl_ops,2031 &props);2032 if (ret)2033 goto error;2034 2035 ov08x->sd.ctrl_handler = ctrl_hdlr;2036 2037 return 0;2038 2039error:2040 v4l2_ctrl_handler_free(ctrl_hdlr);2041 mutex_destroy(&ov08x->mutex);2042 2043 return ret;2044}2045 2046static void ov08x40_free_controls(struct ov08x40 *ov08x)2047{2048 v4l2_ctrl_handler_free(ov08x->sd.ctrl_handler);2049 mutex_destroy(&ov08x->mutex);2050}2051 2052static int ov08x40_check_hwcfg(struct device *dev)2053{2054 struct v4l2_fwnode_endpoint bus_cfg = {2055 .bus_type = V4L2_MBUS_CSI2_DPHY2056 };2057 struct fwnode_handle *ep;2058 struct fwnode_handle *fwnode = dev_fwnode(dev);2059 unsigned int i, j;2060 int ret;2061 u32 ext_clk;2062 2063 if (!fwnode)2064 return -ENXIO;2065 2066 ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",2067 &ext_clk);2068 if (ret) {2069 dev_err(dev, "can't get clock frequency");2070 return ret;2071 }2072 2073 if (ext_clk != OV08X40_EXT_CLK) {2074 dev_err(dev, "external clock %d is not supported",2075 ext_clk);2076 return -EINVAL;2077 }2078 2079 ep = fwnode_graph_get_next_endpoint(fwnode, NULL);2080 if (!ep)2081 return -ENXIO;2082 2083 ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);2084 fwnode_handle_put(ep);2085 if (ret)2086 return ret;2087 2088 if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV08X40_DATA_LANES) {2089 dev_err(dev, "number of CSI2 data lanes %d is not supported",2090 bus_cfg.bus.mipi_csi2.num_data_lanes);2091 ret = -EINVAL;2092 goto out_err;2093 }2094 2095 if (!bus_cfg.nr_of_link_frequencies) {2096 dev_err(dev, "no link frequencies defined");2097 ret = -EINVAL;2098 goto out_err;2099 }2100 2101 for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {2102 for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {2103 if (link_freq_menu_items[i] ==2104 bus_cfg.link_frequencies[j])2105 break;2106 }2107 2108 if (j == bus_cfg.nr_of_link_frequencies) {2109 dev_err(dev, "no link frequency %lld supported",2110 link_freq_menu_items[i]);2111 ret = -EINVAL;2112 goto out_err;2113 }2114 }2115 2116out_err:2117 v4l2_fwnode_endpoint_free(&bus_cfg);2118 2119 return ret;2120}2121 2122static int ov08x40_probe(struct i2c_client *client)2123{2124 struct ov08x40 *ov08x;2125 int ret;2126 bool full_power;2127 2128 /* Check HW config */2129 ret = ov08x40_check_hwcfg(&client->dev);2130 if (ret) {2131 dev_err(&client->dev, "failed to check hwcfg: %d", ret);2132 return ret;2133 }2134 2135 ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL);2136 if (!ov08x)2137 return -ENOMEM;2138 2139 /* Initialize subdev */2140 v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops);2141 2142 full_power = acpi_dev_state_d0(&client->dev);2143 if (full_power) {2144 /* Check module identity */2145 ret = ov08x40_identify_module(ov08x);2146 if (ret) {2147 dev_err(&client->dev, "failed to find sensor: %d\n", ret);2148 return ret;2149 }2150 }2151 2152 /* Set default mode to max resolution */2153 ov08x->cur_mode = &supported_modes[0];2154 2155 ret = ov08x40_init_controls(ov08x);2156 if (ret)2157 return ret;2158 2159 /* Initialize subdev */2160 ov08x->sd.internal_ops = &ov08x40_internal_ops;2161 ov08x->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;2162 ov08x->sd.entity.ops = &ov08x40_subdev_entity_ops;2163 ov08x->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;2164 2165 /* Initialize source pad */2166 ov08x->pad.flags = MEDIA_PAD_FL_SOURCE;2167 ret = media_entity_pads_init(&ov08x->sd.entity, 1, &ov08x->pad);2168 if (ret) {2169 dev_err(&client->dev, "%s failed:%d\n", __func__, ret);2170 goto error_handler_free;2171 }2172 2173 ret = v4l2_async_register_subdev_sensor(&ov08x->sd);2174 if (ret < 0)2175 goto error_media_entity;2176 2177 if (full_power)2178 pm_runtime_set_active(&client->dev);2179 pm_runtime_enable(&client->dev);2180 pm_runtime_idle(&client->dev);2181 2182 return 0;2183 2184error_media_entity:2185 media_entity_cleanup(&ov08x->sd.entity);2186 2187error_handler_free:2188 ov08x40_free_controls(ov08x);2189 2190 return ret;2191}2192 2193static void ov08x40_remove(struct i2c_client *client)2194{2195 struct v4l2_subdev *sd = i2c_get_clientdata(client);2196 struct ov08x40 *ov08x = to_ov08x40(sd);2197 2198 v4l2_async_unregister_subdev(sd);2199 media_entity_cleanup(&sd->entity);2200 ov08x40_free_controls(ov08x);2201 2202 pm_runtime_disable(&client->dev);2203 pm_runtime_set_suspended(&client->dev);2204}2205 2206#ifdef CONFIG_ACPI2207static const struct acpi_device_id ov08x40_acpi_ids[] = {2208 {"OVTI08F4"},2209 { /* sentinel */ }2210};2211 2212MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids);2213#endif2214 2215static struct i2c_driver ov08x40_i2c_driver = {2216 .driver = {2217 .name = "ov08x40",2218 .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),2219 },2220 .probe = ov08x40_probe,2221 .remove = ov08x40_remove,2222 .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,2223};2224 2225module_i2c_driver(ov08x40_i2c_driver);2226 2227MODULE_AUTHOR("Jason Chen <jason.z.chen@intel.com>");2228MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>");2229MODULE_AUTHOR("Shawn Tu");2230MODULE_DESCRIPTION("OmniVision OV08X40 sensor driver");2231MODULE_LICENSE("GPL");2232