1479 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2022 Intel Corporation.3 4#include <linux/acpi.h>5#include <linux/clk.h>6#include <linux/delay.h>7#include <linux/i2c.h>8#include <linux/module.h>9#include <linux/pm_runtime.h>10#include <linux/regulator/consumer.h>11#include <media/v4l2-ctrls.h>12#include <media/v4l2-device.h>13#include <media/v4l2-fwnode.h>14 15#define OV08D10_SCLK 144000000ULL16#define OV08D10_XVCLK_19_2 1920000017#define OV08D10_ROWCLK 3600018#define OV08D10_DATA_LANES 219#define OV08D10_RGB_DEPTH 1020 21#define OV08D10_REG_PAGE 0xfd22#define OV08D10_REG_GLOBAL_EFFECTIVE 0x0123#define OV08D10_REG_CHIP_ID_0 0x0024#define OV08D10_REG_CHIP_ID_1 0x0125#define OV08D10_ID_MASK GENMASK(15, 0)26#define OV08D10_CHIP_ID 0x560827 28#define OV08D10_REG_MODE_SELECT 0xa029#define OV08D10_MODE_STANDBY 0x0030#define OV08D10_MODE_STREAMING 0x0131 32/* vertical-timings from sensor */33#define OV08D10_REG_VTS_H 0x0534#define OV08D10_REG_VTS_L 0x0635#define OV08D10_VTS_MAX 0x7fff36 37/* Exposure controls from sensor */38#define OV08D10_REG_EXPOSURE_H 0x0239#define OV08D10_REG_EXPOSURE_M 0x0340#define OV08D10_REG_EXPOSURE_L 0x0441#define OV08D10_EXPOSURE_MIN 642#define OV08D10_EXPOSURE_MAX_MARGIN 643#define OV08D10_EXPOSURE_STEP 144 45/* Analog gain controls from sensor */46#define OV08D10_REG_ANALOG_GAIN 0x2447#define OV08D10_ANAL_GAIN_MIN 12848#define OV08D10_ANAL_GAIN_MAX 204749#define OV08D10_ANAL_GAIN_STEP 150 51/* Digital gain controls from sensor */52#define OV08D10_REG_MWB_DGAIN_C 0x2153#define OV08D10_REG_MWB_DGAIN_F 0x2254#define OV08D10_DGTL_GAIN_MIN 055#define OV08D10_DGTL_GAIN_MAX 409556#define OV08D10_DGTL_GAIN_STEP 157#define OV08D10_DGTL_GAIN_DEFAULT 102458 59/* Test Pattern Control */60#define OV08D10_REG_TEST_PATTERN 0x1261#define OV08D10_TEST_PATTERN_ENABLE 0x0162#define OV08D10_TEST_PATTERN_DISABLE 0x0063 64/* Flip Mirror Controls from sensor */65#define OV08D10_REG_FLIP_OPT 0x3266#define OV08D10_REG_FLIP_MASK 0x367 68#define to_ov08d10(_sd) container_of(_sd, struct ov08d10, sd)69 70struct ov08d10_reg {71 u8 address;72 u8 val;73};74 75struct ov08d10_reg_list {76 u32 num_of_regs;77 const struct ov08d10_reg *regs;78};79 80struct ov08d10_link_freq_config {81 const struct ov08d10_reg_list reg_list;82};83 84struct ov08d10_mode {85 /* Frame width in pixels */86 u32 width;87 88 /* Frame height in pixels */89 u32 height;90 91 /* Horizontal timining size */92 u32 hts;93 94 /* Default vertical timining size */95 u32 vts_def;96 97 /* Min vertical timining size */98 u32 vts_min;99 100 /* Link frequency needed for this resolution */101 u32 link_freq_index;102 103 /* Sensor register settings for this resolution */104 const struct ov08d10_reg_list reg_list;105 106 /* Number of data lanes */107 u8 data_lanes;108};109 110/* 3280x2460, 3264x2448 need 720Mbps/lane, 2 lanes */111static const struct ov08d10_reg mipi_data_rate_720mbps[] = {112 {0xfd, 0x00},113 {0x11, 0x2a},114 {0x14, 0x43},115 {0x1a, 0x04},116 {0x1b, 0xe1},117 {0x1e, 0x13},118 {0xb7, 0x02}119};120 121/* 1632x1224 needs 360Mbps/lane, 2 lanes */122static const struct ov08d10_reg mipi_data_rate_360mbps[] = {123 {0xfd, 0x00},124 {0x1a, 0x04},125 {0x1b, 0xe1},126 {0x1d, 0x00},127 {0x1c, 0x19},128 {0x11, 0x2a},129 {0x14, 0x54},130 {0x1e, 0x13},131 {0xb7, 0x02}132};133 134static const struct ov08d10_reg lane_2_mode_3280x2460[] = {135 /* 3280x2460 resolution */136 {0xfd, 0x01},137 {0x12, 0x00},138 {0x03, 0x12},139 {0x04, 0x58},140 {0x07, 0x05},141 {0x21, 0x02},142 {0x24, 0x30},143 {0x33, 0x03},144 {0x01, 0x03},145 {0x19, 0x10},146 {0x42, 0x55},147 {0x43, 0x00},148 {0x47, 0x07},149 {0x48, 0x08},150 {0xb2, 0x7f},151 {0xb3, 0x7b},152 {0xbd, 0x08},153 {0xd2, 0x57},154 {0xd3, 0x10},155 {0xd4, 0x08},156 {0xd5, 0x08},157 {0xd6, 0x06},158 {0xb1, 0x00},159 {0xb4, 0x00},160 {0xb7, 0x0a},161 {0xbc, 0x44},162 {0xbf, 0x48},163 {0xc1, 0x10},164 {0xc3, 0x24},165 {0xc8, 0x03},166 {0xc9, 0xf8},167 {0xe1, 0x33},168 {0xe2, 0xbb},169 {0x51, 0x0c},170 {0x52, 0x0a},171 {0x57, 0x8c},172 {0x59, 0x09},173 {0x5a, 0x08},174 {0x5e, 0x10},175 {0x60, 0x02},176 {0x6d, 0x5c},177 {0x76, 0x16},178 {0x7c, 0x11},179 {0x90, 0x28},180 {0x91, 0x16},181 {0x92, 0x1c},182 {0x93, 0x24},183 {0x95, 0x48},184 {0x9c, 0x06},185 {0xca, 0x0c},186 {0xce, 0x0d},187 {0xfd, 0x01},188 {0xc0, 0x00},189 {0xdd, 0x18},190 {0xde, 0x19},191 {0xdf, 0x32},192 {0xe0, 0x70},193 {0xfd, 0x01},194 {0xc2, 0x05},195 {0xd7, 0x88},196 {0xd8, 0x77},197 {0xd9, 0x00},198 {0xfd, 0x07},199 {0x00, 0xf8},200 {0x01, 0x2b},201 {0x05, 0x40},202 {0x08, 0x06},203 {0x09, 0x11},204 {0x28, 0x6f},205 {0x2a, 0x20},206 {0x2b, 0x05},207 {0x5e, 0x10},208 {0x52, 0x00},209 {0x53, 0x7c},210 {0x54, 0x00},211 {0x55, 0x7c},212 {0x56, 0x00},213 {0x57, 0x7c},214 {0x58, 0x00},215 {0x59, 0x7c},216 {0xfd, 0x02},217 {0x9a, 0x30},218 {0xa8, 0x02},219 {0xfd, 0x02},220 {0xa1, 0x01},221 {0xa2, 0x09},222 {0xa3, 0x9c},223 {0xa5, 0x00},224 {0xa6, 0x0c},225 {0xa7, 0xd0},226 {0xfd, 0x00},227 {0x24, 0x01},228 {0xc0, 0x16},229 {0xc1, 0x08},230 {0xc2, 0x30},231 {0x8e, 0x0c},232 {0x8f, 0xd0},233 {0x90, 0x09},234 {0x91, 0x9c},235 {0xfd, 0x05},236 {0x04, 0x40},237 {0x07, 0x00},238 {0x0d, 0x01},239 {0x0f, 0x01},240 {0x10, 0x00},241 {0x11, 0x00},242 {0x12, 0x0c},243 {0x13, 0xcf},244 {0x14, 0x00},245 {0x15, 0x00},246 {0xfd, 0x00},247 {0x20, 0x0f},248 {0xe7, 0x03},249 {0xe7, 0x00}250};251 252static const struct ov08d10_reg lane_2_mode_3264x2448[] = {253 /* 3264x2448 resolution */254 {0xfd, 0x01},255 {0x12, 0x00},256 {0x03, 0x12},257 {0x04, 0x58},258 {0x07, 0x05},259 {0x21, 0x02},260 {0x24, 0x30},261 {0x33, 0x03},262 {0x01, 0x03},263 {0x19, 0x10},264 {0x42, 0x55},265 {0x43, 0x00},266 {0x47, 0x07},267 {0x48, 0x08},268 {0xb2, 0x7f},269 {0xb3, 0x7b},270 {0xbd, 0x08},271 {0xd2, 0x57},272 {0xd3, 0x10},273 {0xd4, 0x08},274 {0xd5, 0x08},275 {0xd6, 0x06},276 {0xb1, 0x00},277 {0xb4, 0x00},278 {0xb7, 0x0a},279 {0xbc, 0x44},280 {0xbf, 0x48},281 {0xc1, 0x10},282 {0xc3, 0x24},283 {0xc8, 0x03},284 {0xc9, 0xf8},285 {0xe1, 0x33},286 {0xe2, 0xbb},287 {0x51, 0x0c},288 {0x52, 0x0a},289 {0x57, 0x8c},290 {0x59, 0x09},291 {0x5a, 0x08},292 {0x5e, 0x10},293 {0x60, 0x02},294 {0x6d, 0x5c},295 {0x76, 0x16},296 {0x7c, 0x11},297 {0x90, 0x28},298 {0x91, 0x16},299 {0x92, 0x1c},300 {0x93, 0x24},301 {0x95, 0x48},302 {0x9c, 0x06},303 {0xca, 0x0c},304 {0xce, 0x0d},305 {0xfd, 0x01},306 {0xc0, 0x00},307 {0xdd, 0x18},308 {0xde, 0x19},309 {0xdf, 0x32},310 {0xe0, 0x70},311 {0xfd, 0x01},312 {0xc2, 0x05},313 {0xd7, 0x88},314 {0xd8, 0x77},315 {0xd9, 0x00},316 {0xfd, 0x07},317 {0x00, 0xf8},318 {0x01, 0x2b},319 {0x05, 0x40},320 {0x08, 0x06},321 {0x09, 0x11},322 {0x28, 0x6f},323 {0x2a, 0x20},324 {0x2b, 0x05},325 {0x5e, 0x10},326 {0x52, 0x00},327 {0x53, 0x7c},328 {0x54, 0x00},329 {0x55, 0x7c},330 {0x56, 0x00},331 {0x57, 0x7c},332 {0x58, 0x00},333 {0x59, 0x7c},334 {0xfd, 0x02},335 {0x9a, 0x30},336 {0xa8, 0x02},337 {0xfd, 0x02},338 {0xa1, 0x09},339 {0xa2, 0x09},340 {0xa3, 0x90},341 {0xa5, 0x08},342 {0xa6, 0x0c},343 {0xa7, 0xc0},344 {0xfd, 0x00},345 {0x24, 0x01},346 {0xc0, 0x16},347 {0xc1, 0x08},348 {0xc2, 0x30},349 {0x8e, 0x0c},350 {0x8f, 0xc0},351 {0x90, 0x09},352 {0x91, 0x90},353 {0xfd, 0x05},354 {0x04, 0x40},355 {0x07, 0x00},356 {0x0d, 0x01},357 {0x0f, 0x01},358 {0x10, 0x00},359 {0x11, 0x00},360 {0x12, 0x0c},361 {0x13, 0xcf},362 {0x14, 0x00},363 {0x15, 0x00},364 {0xfd, 0x00},365 {0x20, 0x0f},366 {0xe7, 0x03},367 {0xe7, 0x00}368};369 370static const struct ov08d10_reg lane_2_mode_1632x1224[] = {371 /* 1640x1232 resolution */372 {0xfd, 0x01},373 {0x1a, 0x0a},374 {0x1b, 0x08},375 {0x2a, 0x01},376 {0x2b, 0x9a},377 {0xfd, 0x01},378 {0x12, 0x00},379 {0x03, 0x05},380 {0x04, 0xe2},381 {0x07, 0x05},382 {0x21, 0x02},383 {0x24, 0x30},384 {0x33, 0x03},385 {0x31, 0x06},386 {0x33, 0x03},387 {0x01, 0x03},388 {0x19, 0x10},389 {0x42, 0x55},390 {0x43, 0x00},391 {0x47, 0x07},392 {0x48, 0x08},393 {0xb2, 0x7f},394 {0xb3, 0x7b},395 {0xbd, 0x08},396 {0xd2, 0x57},397 {0xd3, 0x10},398 {0xd4, 0x08},399 {0xd5, 0x08},400 {0xd6, 0x06},401 {0xb1, 0x00},402 {0xb4, 0x00},403 {0xb7, 0x0a},404 {0xbc, 0x44},405 {0xbf, 0x48},406 {0xc1, 0x10},407 {0xc3, 0x24},408 {0xc8, 0x03},409 {0xc9, 0xf8},410 {0xe1, 0x33},411 {0xe2, 0xbb},412 {0x51, 0x0c},413 {0x52, 0x0a},414 {0x57, 0x8c},415 {0x59, 0x09},416 {0x5a, 0x08},417 {0x5e, 0x10},418 {0x60, 0x02},419 {0x6d, 0x5c},420 {0x76, 0x16},421 {0x7c, 0x1a},422 {0x90, 0x28},423 {0x91, 0x16},424 {0x92, 0x1c},425 {0x93, 0x24},426 {0x95, 0x48},427 {0x9c, 0x06},428 {0xca, 0x0c},429 {0xce, 0x0d},430 {0xfd, 0x01},431 {0xc0, 0x00},432 {0xdd, 0x18},433 {0xde, 0x19},434 {0xdf, 0x32},435 {0xe0, 0x70},436 {0xfd, 0x01},437 {0xc2, 0x05},438 {0xd7, 0x88},439 {0xd8, 0x77},440 {0xd9, 0x00},441 {0xfd, 0x07},442 {0x00, 0xf8},443 {0x01, 0x2b},444 {0x05, 0x40},445 {0x08, 0x03},446 {0x09, 0x08},447 {0x28, 0x6f},448 {0x2a, 0x20},449 {0x2b, 0x05},450 {0x2c, 0x01},451 {0x50, 0x02},452 {0x51, 0x03},453 {0x5e, 0x00},454 {0x52, 0x00},455 {0x53, 0x7c},456 {0x54, 0x00},457 {0x55, 0x7c},458 {0x56, 0x00},459 {0x57, 0x7c},460 {0x58, 0x00},461 {0x59, 0x7c},462 {0xfd, 0x02},463 {0x9a, 0x30},464 {0xa8, 0x02},465 {0xfd, 0x02},466 {0xa9, 0x04},467 {0xaa, 0xd0},468 {0xab, 0x06},469 {0xac, 0x68},470 {0xa1, 0x09},471 {0xa2, 0x04},472 {0xa3, 0xc8},473 {0xa5, 0x04},474 {0xa6, 0x06},475 {0xa7, 0x60},476 {0xfd, 0x05},477 {0x06, 0x80},478 {0x18, 0x06},479 {0x19, 0x68},480 {0xfd, 0x00},481 {0x24, 0x01},482 {0xc0, 0x16},483 {0xc1, 0x08},484 {0xc2, 0x30},485 {0x8e, 0x06},486 {0x8f, 0x60},487 {0x90, 0x04},488 {0x91, 0xc8},489 {0x93, 0x0e},490 {0x94, 0x77},491 {0x95, 0x77},492 {0x96, 0x10},493 {0x98, 0x88},494 {0x9c, 0x1a},495 {0xfd, 0x05},496 {0x04, 0x40},497 {0x07, 0x99},498 {0x0d, 0x03},499 {0x0f, 0x03},500 {0x10, 0x00},501 {0x11, 0x00},502 {0x12, 0x0c},503 {0x13, 0xcf},504 {0x14, 0x00},505 {0x15, 0x00},506 {0xfd, 0x00},507 {0x20, 0x0f},508 {0xe7, 0x03},509 {0xe7, 0x00},510};511 512static const char * const ov08d10_test_pattern_menu[] = {513 "Disabled",514 "Standard Color Bar",515};516 517struct ov08d10 {518 struct v4l2_subdev sd;519 struct media_pad pad;520 struct v4l2_ctrl_handler ctrl_handler;521 522 struct clk *xvclk;523 524 /* V4L2 Controls */525 struct v4l2_ctrl *link_freq;526 struct v4l2_ctrl *pixel_rate;527 struct v4l2_ctrl *vblank;528 struct v4l2_ctrl *hblank;529 struct v4l2_ctrl *vflip;530 struct v4l2_ctrl *hflip;531 struct v4l2_ctrl *exposure;532 533 /* Current mode */534 const struct ov08d10_mode *cur_mode;535 536 /* To serialize asynchronus callbacks */537 struct mutex mutex;538 539 /* lanes index */540 u8 nlanes;541 542 const struct ov08d10_lane_cfg *priv_lane;543 u8 modes_size;544};545 546struct ov08d10_lane_cfg {547 const s64 link_freq_menu[2];548 const struct ov08d10_link_freq_config link_freq_configs[2];549 const struct ov08d10_mode sp_modes[3];550};551 552static const struct ov08d10_lane_cfg lane_cfg_2 = {553 {554 720000000,555 360000000,556 },557 {{558 .reg_list = {559 .num_of_regs =560 ARRAY_SIZE(mipi_data_rate_720mbps),561 .regs = mipi_data_rate_720mbps,562 }563 },564 {565 .reg_list = {566 .num_of_regs =567 ARRAY_SIZE(mipi_data_rate_360mbps),568 .regs = mipi_data_rate_360mbps,569 }570 }},571 {{572 .width = 3280,573 .height = 2460,574 .hts = 1840,575 .vts_def = 2504,576 .vts_min = 2504,577 .reg_list = {578 .num_of_regs = ARRAY_SIZE(lane_2_mode_3280x2460),579 .regs = lane_2_mode_3280x2460,580 },581 .link_freq_index = 0,582 .data_lanes = 2,583 },584 {585 .width = 3264,586 .height = 2448,587 .hts = 1840,588 .vts_def = 2504,589 .vts_min = 2504,590 .reg_list = {591 .num_of_regs = ARRAY_SIZE(lane_2_mode_3264x2448),592 .regs = lane_2_mode_3264x2448,593 },594 .link_freq_index = 0,595 .data_lanes = 2,596 },597 {598 .width = 1632,599 .height = 1224,600 .hts = 1912,601 .vts_def = 3736,602 .vts_min = 3736,603 .reg_list = {604 .num_of_regs = ARRAY_SIZE(lane_2_mode_1632x1224),605 .regs = lane_2_mode_1632x1224,606 },607 .link_freq_index = 1,608 .data_lanes = 2,609 }}610};611 612static u32 ov08d10_get_format_code(struct ov08d10 *ov08d10)613{614 static const u32 codes[2][2] = {615 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10},616 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10},617 };618 619 return codes[ov08d10->vflip->val][ov08d10->hflip->val];620}621 622static unsigned int ov08d10_modes_num(const struct ov08d10 *ov08d10)623{624 unsigned int i, count = 0;625 626 for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->sp_modes); i++) {627 if (ov08d10->priv_lane->sp_modes[i].width == 0)628 break;629 count++;630 }631 632 return count;633}634 635static u64 to_rate(const s64 *link_freq_menu,636 u32 f_index, u8 nlanes)637{638 u64 pixel_rate = link_freq_menu[f_index] * 2 * nlanes;639 640 do_div(pixel_rate, OV08D10_RGB_DEPTH);641 642 return pixel_rate;643}644 645static u64 to_pixels_per_line(const s64 *link_freq_menu, u32 hts,646 u32 f_index, u8 nlanes)647{648 u64 ppl = hts * to_rate(link_freq_menu, f_index, nlanes);649 650 do_div(ppl, OV08D10_SCLK);651 652 return ppl;653}654 655static int ov08d10_write_reg_list(struct ov08d10 *ov08d10,656 const struct ov08d10_reg_list *r_list)657{658 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);659 unsigned int i;660 int ret;661 662 for (i = 0; i < r_list->num_of_regs; i++) {663 ret = i2c_smbus_write_byte_data(client, r_list->regs[i].address,664 r_list->regs[i].val);665 if (ret) {666 dev_err_ratelimited(&client->dev,667 "failed to write reg 0x%2.2x. error = %d",668 r_list->regs[i].address, ret);669 return ret;670 }671 }672 673 return 0;674}675 676static int ov08d10_update_analog_gain(struct ov08d10 *ov08d10, u32 a_gain)677{678 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);679 u8 val;680 int ret;681 682 val = ((a_gain >> 3) & 0xFF);683 /* CIS control registers */684 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);685 if (ret < 0)686 return ret;687 688 /* update AGAIN */689 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_ANALOG_GAIN, val);690 if (ret < 0)691 return ret;692 693 return i2c_smbus_write_byte_data(client,694 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);695}696 697static int ov08d10_update_digital_gain(struct ov08d10 *ov08d10, u32 d_gain)698{699 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);700 u8 val;701 int ret;702 703 d_gain = (d_gain >> 1);704 /* CIS control registers */705 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);706 if (ret < 0)707 return ret;708 709 val = ((d_gain >> 8) & 0x3F);710 /* update DGAIN */711 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_C, val);712 if (ret < 0)713 return ret;714 715 val = d_gain & 0xFF;716 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_F, val);717 if (ret < 0)718 return ret;719 720 return i2c_smbus_write_byte_data(client,721 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);722}723 724static int ov08d10_set_exposure(struct ov08d10 *ov08d10, u32 exposure)725{726 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);727 u8 val;728 u8 hts_h, hts_l;729 u32 hts, cur_vts, exp_cal;730 int ret;731 732 cur_vts = ov08d10->cur_mode->vts_def;733 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);734 if (ret < 0)735 return ret;736 737 hts_h = i2c_smbus_read_byte_data(client, 0x37);738 hts_l = i2c_smbus_read_byte_data(client, 0x38);739 hts = ((hts_h << 8) | (hts_l));740 exp_cal = 66 * OV08D10_ROWCLK / hts;741 exposure = exposure * exp_cal / (cur_vts - OV08D10_EXPOSURE_MAX_MARGIN);742 /* CIS control registers */743 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);744 if (ret < 0)745 return ret;746 747 /* update exposure */748 val = ((exposure >> 16) & 0xFF);749 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_H, val);750 if (ret < 0)751 return ret;752 753 val = ((exposure >> 8) & 0xFF);754 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_M, val);755 if (ret < 0)756 return ret;757 758 val = exposure & 0xFF;759 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_L, val);760 if (ret < 0)761 return ret;762 763 return i2c_smbus_write_byte_data(client,764 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);765}766 767static int ov08d10_set_vblank(struct ov08d10 *ov08d10, u32 vblank)768{769 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);770 u8 val;771 int ret;772 773 /* CIS control registers */774 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);775 if (ret < 0)776 return ret;777 778 val = ((vblank >> 8) & 0xFF);779 /* update vblank */780 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_H, val);781 if (ret < 0)782 return ret;783 784 val = vblank & 0xFF;785 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_L, val);786 if (ret < 0)787 return ret;788 789 return i2c_smbus_write_byte_data(client,790 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);791}792 793static int ov08d10_test_pattern(struct ov08d10 *ov08d10, u32 pattern)794{795 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);796 u8 val;797 int ret;798 799 if (pattern)800 val = OV08D10_TEST_PATTERN_ENABLE;801 else802 val = OV08D10_TEST_PATTERN_DISABLE;803 804 /* CIS control registers */805 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);806 if (ret < 0)807 return ret;808 809 ret = i2c_smbus_write_byte_data(client,810 OV08D10_REG_TEST_PATTERN, val);811 if (ret < 0)812 return ret;813 814 return i2c_smbus_write_byte_data(client,815 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);816}817 818static int ov08d10_set_ctrl_flip(struct ov08d10 *ov08d10, u32 ctrl_val)819{820 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);821 u8 val;822 int ret;823 824 /* System control registers */825 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);826 if (ret < 0)827 return ret;828 829 ret = i2c_smbus_read_byte_data(client, OV08D10_REG_FLIP_OPT);830 if (ret < 0)831 return ret;832 833 val = ret | (ctrl_val & OV08D10_REG_FLIP_MASK);834 835 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);836 if (ret < 0)837 return ret;838 839 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_FLIP_OPT, val);840 841 if (ret < 0)842 return ret;843 844 return i2c_smbus_write_byte_data(client,845 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);846}847 848static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl)849{850 struct ov08d10 *ov08d10 = container_of(ctrl->handler,851 struct ov08d10, ctrl_handler);852 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);853 s64 exposure_max;854 int ret;855 856 /* Propagate change of current control to all related controls */857 if (ctrl->id == V4L2_CID_VBLANK) {858 /* Update max exposure while meeting expected vblanking */859 exposure_max = ov08d10->cur_mode->height + ctrl->val -860 OV08D10_EXPOSURE_MAX_MARGIN;861 __v4l2_ctrl_modify_range(ov08d10->exposure,862 ov08d10->exposure->minimum,863 exposure_max, ov08d10->exposure->step,864 exposure_max);865 }866 867 /* V4L2 controls values will be applied only when power is already up */868 if (!pm_runtime_get_if_in_use(&client->dev))869 return 0;870 871 switch (ctrl->id) {872 case V4L2_CID_ANALOGUE_GAIN:873 ret = ov08d10_update_analog_gain(ov08d10, ctrl->val);874 break;875 876 case V4L2_CID_DIGITAL_GAIN:877 ret = ov08d10_update_digital_gain(ov08d10, ctrl->val);878 break;879 880 case V4L2_CID_EXPOSURE:881 ret = ov08d10_set_exposure(ov08d10, ctrl->val);882 break;883 884 case V4L2_CID_VBLANK:885 ret = ov08d10_set_vblank(ov08d10, ctrl->val);886 break;887 888 case V4L2_CID_TEST_PATTERN:889 ret = ov08d10_test_pattern(ov08d10, ctrl->val);890 break;891 892 case V4L2_CID_HFLIP:893 case V4L2_CID_VFLIP:894 ret = ov08d10_set_ctrl_flip(ov08d10,895 ov08d10->hflip->val |896 ov08d10->vflip->val << 1);897 break;898 899 default:900 ret = -EINVAL;901 break;902 }903 904 pm_runtime_put(&client->dev);905 906 return ret;907}908 909static const struct v4l2_ctrl_ops ov08d10_ctrl_ops = {910 .s_ctrl = ov08d10_set_ctrl,911};912 913static int ov08d10_init_controls(struct ov08d10 *ov08d10)914{915 struct v4l2_ctrl_handler *ctrl_hdlr;916 u8 link_freq_size;917 s64 exposure_max;918 s64 vblank_def;919 s64 vblank_min;920 s64 h_blank;921 s64 pixel_rate_max;922 const struct ov08d10_mode *mode;923 int ret;924 925 ctrl_hdlr = &ov08d10->ctrl_handler;926 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);927 if (ret)928 return ret;929 930 ctrl_hdlr->lock = &ov08d10->mutex;931 link_freq_size = ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu);932 ov08d10->link_freq =933 v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov08d10_ctrl_ops,934 V4L2_CID_LINK_FREQ,935 link_freq_size - 1,936 0,937 ov08d10->priv_lane->link_freq_menu);938 if (ov08d10->link_freq)939 ov08d10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;940 941 pixel_rate_max = to_rate(ov08d10->priv_lane->link_freq_menu, 0,942 ov08d10->cur_mode->data_lanes);943 ov08d10->pixel_rate =944 v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,945 V4L2_CID_PIXEL_RATE, 0, pixel_rate_max, 1,946 pixel_rate_max);947 948 mode = ov08d10->cur_mode;949 vblank_def = mode->vts_def - mode->height;950 vblank_min = mode->vts_min - mode->height;951 ov08d10->vblank =952 v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,953 V4L2_CID_VBLANK, vblank_min,954 OV08D10_VTS_MAX - mode->height, 1,955 vblank_def);956 957 h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu,958 mode->hts, mode->link_freq_index,959 mode->data_lanes) -960 mode->width;961 ov08d10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,962 V4L2_CID_HBLANK, h_blank, h_blank,963 1, h_blank);964 if (ov08d10->hblank)965 ov08d10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;966 967 v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,968 OV08D10_ANAL_GAIN_MIN, OV08D10_ANAL_GAIN_MAX,969 OV08D10_ANAL_GAIN_STEP, OV08D10_ANAL_GAIN_MIN);970 971 v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_DIGITAL_GAIN,972 OV08D10_DGTL_GAIN_MIN, OV08D10_DGTL_GAIN_MAX,973 OV08D10_DGTL_GAIN_STEP, OV08D10_DGTL_GAIN_DEFAULT);974 975 exposure_max = mode->vts_def - OV08D10_EXPOSURE_MAX_MARGIN;976 ov08d10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,977 V4L2_CID_EXPOSURE,978 OV08D10_EXPOSURE_MIN,979 exposure_max,980 OV08D10_EXPOSURE_STEP,981 exposure_max);982 983 v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov08d10_ctrl_ops,984 V4L2_CID_TEST_PATTERN,985 ARRAY_SIZE(ov08d10_test_pattern_menu) - 1,986 0, 0, ov08d10_test_pattern_menu);987 988 ov08d10->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,989 V4L2_CID_HFLIP, 0, 1, 1, 0);990 if (ov08d10->hflip)991 ov08d10->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;992 ov08d10->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,993 V4L2_CID_VFLIP, 0, 1, 1, 0);994 if (ov08d10->vflip)995 ov08d10->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;996 997 if (ctrl_hdlr->error)998 return ctrl_hdlr->error;999 1000 ov08d10->sd.ctrl_handler = ctrl_hdlr;1001 1002 return 0;1003}1004 1005static void ov08d10_update_pad_format(struct ov08d10 *ov08d10,1006 const struct ov08d10_mode *mode,1007 struct v4l2_mbus_framefmt *fmt)1008{1009 fmt->width = mode->width;1010 fmt->height = mode->height;1011 fmt->code = ov08d10_get_format_code(ov08d10);1012 fmt->field = V4L2_FIELD_NONE;1013}1014 1015static int ov08d10_start_streaming(struct ov08d10 *ov08d10)1016{1017 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1018 const struct ov08d10_reg_list *reg_list;1019 int link_freq_index, ret;1020 1021 link_freq_index = ov08d10->cur_mode->link_freq_index;1022 reg_list =1023 &ov08d10->priv_lane->link_freq_configs[link_freq_index].reg_list;1024 1025 /* soft reset */1026 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1027 if (ret < 0) {1028 dev_err(&client->dev, "failed to reset sensor");1029 return ret;1030 }1031 ret = i2c_smbus_write_byte_data(client, 0x20, 0x0e);1032 if (ret < 0) {1033 dev_err(&client->dev, "failed to reset sensor");1034 return ret;1035 }1036 usleep_range(3000, 4000);1037 ret = i2c_smbus_write_byte_data(client, 0x20, 0x0b);1038 if (ret < 0) {1039 dev_err(&client->dev, "failed to reset sensor");1040 return ret;1041 }1042 1043 /* update sensor setting */1044 ret = ov08d10_write_reg_list(ov08d10, reg_list);1045 if (ret) {1046 dev_err(&client->dev, "failed to set plls");1047 return ret;1048 }1049 1050 reg_list = &ov08d10->cur_mode->reg_list;1051 ret = ov08d10_write_reg_list(ov08d10, reg_list);1052 if (ret) {1053 dev_err(&client->dev, "failed to set mode");1054 return ret;1055 }1056 1057 ret = __v4l2_ctrl_handler_setup(ov08d10->sd.ctrl_handler);1058 if (ret)1059 return ret;1060 1061 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1062 if (ret < 0)1063 return ret;1064 1065 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT,1066 OV08D10_MODE_STREAMING);1067 if (ret < 0)1068 return ret;1069 1070 return i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);1071}1072 1073static void ov08d10_stop_streaming(struct ov08d10 *ov08d10)1074{1075 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1076 int ret;1077 1078 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1079 if (ret < 0) {1080 dev_err(&client->dev, "failed to stop streaming");1081 return;1082 }1083 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT,1084 OV08D10_MODE_STANDBY);1085 if (ret < 0) {1086 dev_err(&client->dev, "failed to stop streaming");1087 return;1088 }1089 1090 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);1091 if (ret < 0) {1092 dev_err(&client->dev, "failed to stop streaming");1093 return;1094 }1095}1096 1097static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable)1098{1099 struct ov08d10 *ov08d10 = to_ov08d10(sd);1100 struct i2c_client *client = v4l2_get_subdevdata(sd);1101 int ret = 0;1102 1103 mutex_lock(&ov08d10->mutex);1104 if (enable) {1105 ret = pm_runtime_resume_and_get(&client->dev);1106 if (ret < 0) {1107 mutex_unlock(&ov08d10->mutex);1108 return ret;1109 }1110 1111 ret = ov08d10_start_streaming(ov08d10);1112 if (ret) {1113 enable = 0;1114 ov08d10_stop_streaming(ov08d10);1115 pm_runtime_put(&client->dev);1116 }1117 } else {1118 ov08d10_stop_streaming(ov08d10);1119 pm_runtime_put(&client->dev);1120 }1121 1122 /* vflip and hflip cannot change during streaming */1123 __v4l2_ctrl_grab(ov08d10->vflip, enable);1124 __v4l2_ctrl_grab(ov08d10->hflip, enable);1125 1126 mutex_unlock(&ov08d10->mutex);1127 1128 return ret;1129}1130 1131static int ov08d10_set_format(struct v4l2_subdev *sd,1132 struct v4l2_subdev_state *sd_state,1133 struct v4l2_subdev_format *fmt)1134{1135 struct ov08d10 *ov08d10 = to_ov08d10(sd);1136 const struct ov08d10_mode *mode;1137 s32 vblank_def, h_blank;1138 s64 pixel_rate;1139 1140 mode = v4l2_find_nearest_size(ov08d10->priv_lane->sp_modes,1141 ov08d10->modes_size,1142 width, height, fmt->format.width,1143 fmt->format.height);1144 1145 mutex_lock(&ov08d10->mutex);1146 ov08d10_update_pad_format(ov08d10, mode, &fmt->format);1147 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1148 *v4l2_subdev_state_get_format(sd_state, fmt->pad) =1149 fmt->format;1150 } else {1151 ov08d10->cur_mode = mode;1152 __v4l2_ctrl_s_ctrl(ov08d10->link_freq, mode->link_freq_index);1153 pixel_rate = to_rate(ov08d10->priv_lane->link_freq_menu,1154 mode->link_freq_index,1155 ov08d10->cur_mode->data_lanes);1156 __v4l2_ctrl_s_ctrl_int64(ov08d10->pixel_rate, pixel_rate);1157 1158 /* Update limits and set FPS to default */1159 vblank_def = mode->vts_def - mode->height;1160 __v4l2_ctrl_modify_range(ov08d10->vblank,1161 mode->vts_min - mode->height,1162 OV08D10_VTS_MAX - mode->height, 1,1163 vblank_def);1164 __v4l2_ctrl_s_ctrl(ov08d10->vblank, vblank_def);1165 h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu,1166 mode->hts,1167 mode->link_freq_index,1168 ov08d10->cur_mode->data_lanes)1169 - mode->width;1170 __v4l2_ctrl_modify_range(ov08d10->hblank, h_blank, h_blank, 1,1171 h_blank);1172 }1173 1174 mutex_unlock(&ov08d10->mutex);1175 1176 return 0;1177}1178 1179static int ov08d10_get_format(struct v4l2_subdev *sd,1180 struct v4l2_subdev_state *sd_state,1181 struct v4l2_subdev_format *fmt)1182{1183 struct ov08d10 *ov08d10 = to_ov08d10(sd);1184 1185 mutex_lock(&ov08d10->mutex);1186 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)1187 fmt->format = *v4l2_subdev_state_get_format(sd_state,1188 fmt->pad);1189 else1190 ov08d10_update_pad_format(ov08d10, ov08d10->cur_mode,1191 &fmt->format);1192 1193 mutex_unlock(&ov08d10->mutex);1194 1195 return 0;1196}1197 1198static int ov08d10_enum_mbus_code(struct v4l2_subdev *sd,1199 struct v4l2_subdev_state *sd_state,1200 struct v4l2_subdev_mbus_code_enum *code)1201{1202 struct ov08d10 *ov08d10 = to_ov08d10(sd);1203 1204 if (code->index > 0)1205 return -EINVAL;1206 1207 mutex_lock(&ov08d10->mutex);1208 code->code = ov08d10_get_format_code(ov08d10);1209 mutex_unlock(&ov08d10->mutex);1210 1211 return 0;1212}1213 1214static int ov08d10_enum_frame_size(struct v4l2_subdev *sd,1215 struct v4l2_subdev_state *sd_state,1216 struct v4l2_subdev_frame_size_enum *fse)1217{1218 struct ov08d10 *ov08d10 = to_ov08d10(sd);1219 1220 if (fse->index >= ov08d10->modes_size)1221 return -EINVAL;1222 1223 mutex_lock(&ov08d10->mutex);1224 if (fse->code != ov08d10_get_format_code(ov08d10)) {1225 mutex_unlock(&ov08d10->mutex);1226 return -EINVAL;1227 }1228 mutex_unlock(&ov08d10->mutex);1229 1230 fse->min_width = ov08d10->priv_lane->sp_modes[fse->index].width;1231 fse->max_width = fse->min_width;1232 fse->min_height = ov08d10->priv_lane->sp_modes[fse->index].height;1233 fse->max_height = fse->min_height;1234 1235 return 0;1236}1237 1238static int ov08d10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1239{1240 struct ov08d10 *ov08d10 = to_ov08d10(sd);1241 1242 mutex_lock(&ov08d10->mutex);1243 ov08d10_update_pad_format(ov08d10, &ov08d10->priv_lane->sp_modes[0],1244 v4l2_subdev_state_get_format(fh->state, 0));1245 mutex_unlock(&ov08d10->mutex);1246 1247 return 0;1248}1249 1250static const struct v4l2_subdev_video_ops ov08d10_video_ops = {1251 .s_stream = ov08d10_set_stream,1252};1253 1254static const struct v4l2_subdev_pad_ops ov08d10_pad_ops = {1255 .set_fmt = ov08d10_set_format,1256 .get_fmt = ov08d10_get_format,1257 .enum_mbus_code = ov08d10_enum_mbus_code,1258 .enum_frame_size = ov08d10_enum_frame_size,1259};1260 1261static const struct v4l2_subdev_ops ov08d10_subdev_ops = {1262 .video = &ov08d10_video_ops,1263 .pad = &ov08d10_pad_ops,1264};1265 1266static const struct v4l2_subdev_internal_ops ov08d10_internal_ops = {1267 .open = ov08d10_open,1268};1269 1270static int ov08d10_identify_module(struct ov08d10 *ov08d10)1271{1272 struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1273 u32 val;1274 u16 chip_id;1275 int ret;1276 1277 /* System control registers */1278 ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1279 if (ret < 0)1280 return ret;1281 1282 /* Validate the chip ID */1283 ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_0);1284 if (ret < 0)1285 return ret;1286 1287 val = ret << 8;1288 1289 ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_1);1290 if (ret < 0)1291 return ret;1292 1293 chip_id = val | ret;1294 1295 if ((chip_id & OV08D10_ID_MASK) != OV08D10_CHIP_ID) {1296 dev_err(&client->dev, "unexpected sensor id(0x%04x)\n",1297 chip_id);1298 return -EINVAL;1299 }1300 1301 return 0;1302}1303 1304static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10, struct device *dev)1305{1306 struct fwnode_handle *ep;1307 struct fwnode_handle *fwnode = dev_fwnode(dev);1308 struct v4l2_fwnode_endpoint bus_cfg = {1309 .bus_type = V4L2_MBUS_CSI2_DPHY1310 };1311 u32 xvclk_rate;1312 unsigned int i, j;1313 int ret;1314 1315 if (!fwnode)1316 return -ENXIO;1317 1318 ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate);1319 if (ret)1320 return ret;1321 1322 if (xvclk_rate != OV08D10_XVCLK_19_2)1323 dev_warn(dev, "external clock rate %u is unsupported",1324 xvclk_rate);1325 1326 ep = fwnode_graph_get_next_endpoint(fwnode, NULL);1327 if (!ep)1328 return -ENXIO;1329 1330 ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);1331 fwnode_handle_put(ep);1332 if (ret)1333 return ret;1334 1335 /* Get number of data lanes */1336 if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {1337 dev_err(dev, "number of CSI2 data lanes %d is not supported",1338 bus_cfg.bus.mipi_csi2.num_data_lanes);1339 ret = -EINVAL;1340 goto check_hwcfg_error;1341 }1342 1343 dev_dbg(dev, "Using %u data lanes\n", ov08d10->cur_mode->data_lanes);1344 1345 ov08d10->priv_lane = &lane_cfg_2;1346 ov08d10->modes_size = ov08d10_modes_num(ov08d10);1347 1348 if (!bus_cfg.nr_of_link_frequencies) {1349 dev_err(dev, "no link frequencies defined");1350 ret = -EINVAL;1351 goto check_hwcfg_error;1352 }1353 1354 for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu); i++) {1355 for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {1356 if (ov08d10->priv_lane->link_freq_menu[i] ==1357 bus_cfg.link_frequencies[j])1358 break;1359 }1360 1361 if (j == bus_cfg.nr_of_link_frequencies) {1362 dev_err(dev, "no link frequency %lld supported",1363 ov08d10->priv_lane->link_freq_menu[i]);1364 ret = -EINVAL;1365 goto check_hwcfg_error;1366 }1367 }1368 1369check_hwcfg_error:1370 v4l2_fwnode_endpoint_free(&bus_cfg);1371 1372 return ret;1373}1374 1375static void ov08d10_remove(struct i2c_client *client)1376{1377 struct v4l2_subdev *sd = i2c_get_clientdata(client);1378 struct ov08d10 *ov08d10 = to_ov08d10(sd);1379 1380 v4l2_async_unregister_subdev(sd);1381 media_entity_cleanup(&sd->entity);1382 v4l2_ctrl_handler_free(sd->ctrl_handler);1383 pm_runtime_disable(&client->dev);1384 mutex_destroy(&ov08d10->mutex);1385}1386 1387static int ov08d10_probe(struct i2c_client *client)1388{1389 struct ov08d10 *ov08d10;1390 int ret;1391 1392 ov08d10 = devm_kzalloc(&client->dev, sizeof(*ov08d10), GFP_KERNEL);1393 if (!ov08d10)1394 return -ENOMEM;1395 1396 ret = ov08d10_get_hwcfg(ov08d10, &client->dev);1397 if (ret) {1398 dev_err(&client->dev, "failed to get HW configuration: %d",1399 ret);1400 return ret;1401 }1402 1403 v4l2_i2c_subdev_init(&ov08d10->sd, client, &ov08d10_subdev_ops);1404 1405 ret = ov08d10_identify_module(ov08d10);1406 if (ret) {1407 dev_err(&client->dev, "failed to find sensor: %d", ret);1408 return ret;1409 }1410 1411 mutex_init(&ov08d10->mutex);1412 ov08d10->cur_mode = &ov08d10->priv_lane->sp_modes[0];1413 ret = ov08d10_init_controls(ov08d10);1414 if (ret) {1415 dev_err(&client->dev, "failed to init controls: %d", ret);1416 goto probe_error_v4l2_ctrl_handler_free;1417 }1418 1419 ov08d10->sd.internal_ops = &ov08d10_internal_ops;1420 ov08d10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1421 ov08d10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1422 ov08d10->pad.flags = MEDIA_PAD_FL_SOURCE;1423 ret = media_entity_pads_init(&ov08d10->sd.entity, 1, &ov08d10->pad);1424 if (ret) {1425 dev_err(&client->dev, "failed to init entity pads: %d", ret);1426 goto probe_error_v4l2_ctrl_handler_free;1427 }1428 1429 ret = v4l2_async_register_subdev_sensor(&ov08d10->sd);1430 if (ret < 0) {1431 dev_err(&client->dev, "failed to register V4L2 subdev: %d",1432 ret);1433 goto probe_error_media_entity_cleanup;1434 }1435 1436 /*1437 * Device is already turned on by i2c-core with ACPI domain PM.1438 * Enable runtime PM and turn off the device.1439 */1440 pm_runtime_set_active(&client->dev);1441 pm_runtime_enable(&client->dev);1442 pm_runtime_idle(&client->dev);1443 1444 return 0;1445 1446probe_error_media_entity_cleanup:1447 media_entity_cleanup(&ov08d10->sd.entity);1448 1449probe_error_v4l2_ctrl_handler_free:1450 v4l2_ctrl_handler_free(ov08d10->sd.ctrl_handler);1451 mutex_destroy(&ov08d10->mutex);1452 1453 return ret;1454}1455 1456#ifdef CONFIG_ACPI1457static const struct acpi_device_id ov08d10_acpi_ids[] = {1458 { "OVTI08D1" },1459 { /* sentinel */ }1460};1461 1462MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids);1463#endif1464 1465static struct i2c_driver ov08d10_i2c_driver = {1466 .driver = {1467 .name = "ov08d10",1468 .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids),1469 },1470 .probe = ov08d10_probe,1471 .remove = ov08d10_remove,1472};1473 1474module_i2c_driver(ov08d10_i2c_driver);1475 1476MODULE_AUTHOR("Su, Jimmy <jimmy.su@intel.com>");1477MODULE_DESCRIPTION("OmniVision ov08d10 sensor driver");1478MODULE_LICENSE("GPL v2");1479