Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: i2c: Add ov08d10 camera sensor driver

Add a v4l2 sub-device driver for the OmniVision ov08d10 image sensor.
This camera sensor is using the i2c bus for control and the
csi-2 bus for data.

The following features are supported:
- manual exposure and analog/digital gain control
- vblank/hblank control
- test pattern
- image vertical flip and horizontal mirror control
- supported resolution:
- 3280x2460 at 30 FPS
- 3264x2448 at 30 FPS
- 1632x1224 at 30 FPS
- supported bayer order output:
- SGRBG10 as default
- SBGGR10 at flip mode
- SRGGB10 at mirror mode
- SGBRG10 at flip + mirror mode

Signed-off-by: Jimmy Su <jimmy.su@intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Jimmy Su and committed by
Mauro Carvalho Chehab
7be91e02 da15b409

+1547
+7
MAINTAINERS
··· 14193 14193 F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml 14194 14194 F: drivers/media/i2c/ov02a10.c 14195 14195 14196 + OMNIVISION OV08D10 SENSOR DRIVER 14197 + M: Jimmy Su <jimmy.su@intel.com> 14198 + L: linux-media@vger.kernel.org 14199 + S: Maintained 14200 + T: git git://linuxtv.org/media_tree.git 14201 + F: drivers/media/i2c/ov08d10.c 14202 + 14196 14203 OMNIVISION OV13858 SENSOR DRIVER 14197 14204 M: Sakari Ailus <sakari.ailus@linux.intel.com> 14198 14205 L: linux-media@vger.kernel.org
+13
drivers/media/i2c/Kconfig
··· 925 925 To compile this driver as a module, choose M here: the 926 926 module will be called ov02a10. 927 927 928 + config VIDEO_OV08D10 929 + tristate "OmniVision OV08D10 sensor support" 930 + depends on I2C && VIDEO_V4L2 931 + select MEDIA_CONTROLLER 932 + select VIDEO_V4L2_SUBDEV_API 933 + select V4L2_FWNODE 934 + help 935 + This is a Video4Linux2 sensor driver for the OmniVision 936 + OV08D10 camera sensor. 937 + 938 + To compile this driver as a module, choose M here: the 939 + module will be called ov08d10. 940 + 928 941 config VIDEO_OV2640 929 942 tristate "OmniVision OV2640 sensor support" 930 943 depends on VIDEO_V4L2 && I2C
+1
drivers/media/i2c/Makefile
··· 65 65 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o 66 66 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o 67 67 obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o 68 + obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o 68 69 obj-$(CONFIG_VIDEO_OV2640) += ov2640.o 69 70 obj-$(CONFIG_VIDEO_OV2680) += ov2680.o 70 71 obj-$(CONFIG_VIDEO_OV2685) += ov2685.o
+1526
drivers/media/i2c/ov08d10.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 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 144000000ULL 16 + #define OV08D10_XVCLK_19_2 19200000 17 + #define OV08D10_ROWCLK 36000 18 + #define OV08D10_DATA_LANES 2 19 + #define OV08D10_RGB_DEPTH 10 20 + 21 + #define OV08D10_REG_PAGE 0xfd 22 + #define OV08D10_REG_GLOBAL_EFFECTIVE 0x01 23 + #define OV08D10_REG_CHIP_ID_0 0x00 24 + #define OV08D10_REG_CHIP_ID_1 0x01 25 + #define OV08D10_ID_MASK GENMASK(15, 0) 26 + #define OV08D10_CHIP_ID 0x5608 27 + 28 + #define OV08D10_REG_MODE_SELECT 0xa0 29 + #define OV08D10_MODE_STANDBY 0x00 30 + #define OV08D10_MODE_STREAMING 0x01 31 + 32 + /* vertical-timings from sensor */ 33 + #define OV08D10_REG_VTS_H 0x05 34 + #define OV08D10_REG_VTS_L 0x06 35 + #define OV08D10_VTS_MAX 0x7fff 36 + 37 + /* Exposure controls from sensor */ 38 + #define OV08D10_REG_EXPOSURE_H 0x02 39 + #define OV08D10_REG_EXPOSURE_M 0x03 40 + #define OV08D10_REG_EXPOSURE_L 0x04 41 + #define OV08D10_EXPOSURE_MIN 6 42 + #define OV08D10_EXPOSURE_MAX_MARGIN 6 43 + #define OV08D10_EXPOSURE_STEP 1 44 + 45 + /* Analog gain controls from sensor */ 46 + #define OV08D10_REG_ANALOG_GAIN 0x24 47 + #define OV08D10_ANAL_GAIN_MIN 128 48 + #define OV08D10_ANAL_GAIN_MAX 2047 49 + #define OV08D10_ANAL_GAIN_STEP 1 50 + 51 + /* Digital gain controls from sensor */ 52 + #define OV08D10_REG_MWB_DGAIN_C 0x21 53 + #define OV08D10_REG_MWB_DGAIN_F 0x22 54 + #define OV08D10_DGTL_GAIN_MIN 0 55 + #define OV08D10_DGTL_GAIN_MAX 4095 56 + #define OV08D10_DGTL_GAIN_STEP 1 57 + #define OV08D10_DGTL_GAIN_DEFAULT 1024 58 + 59 + /* Test Pattern Control */ 60 + #define OV08D10_REG_TEST_PATTERN 0x12 61 + #define OV08D10_TEST_PATTERN_ENABLE 0x01 62 + #define OV08D10_TEST_PATTERN_DISABLE 0x00 63 + 64 + /* Flip Mirror Controls from sensor */ 65 + #define OV08D10_REG_FLIP_OPT 0x32 66 + #define OV08D10_REG_FLIP_MASK 0x3 67 + 68 + #define to_ov08d10(_sd) container_of(_sd, struct ov08d10, sd) 69 + 70 + struct ov08d10_reg { 71 + u8 address; 72 + u8 val; 73 + }; 74 + 75 + struct ov08d10_reg_list { 76 + u32 num_of_regs; 77 + const struct ov08d10_reg *regs; 78 + }; 79 + 80 + struct ov08d10_link_freq_config { 81 + const struct ov08d10_reg_list reg_list; 82 + }; 83 + 84 + struct 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 */ 111 + static 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 */ 122 + static 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 + 134 + static 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 + 252 + static 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 + 370 + static 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 + 512 + static const char * const ov08d10_test_pattern_menu[] = { 513 + "Disabled", 514 + "Standard Color Bar", 515 + }; 516 + 517 + struct 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 + /* Streaming on/off */ 540 + bool streaming; 541 + 542 + /* lanes index */ 543 + u8 nlanes; 544 + 545 + const struct ov08d10_lane_cfg *priv_lane; 546 + u8 modes_size; 547 + }; 548 + 549 + struct ov08d10_lane_cfg { 550 + const s64 link_freq_menu[2]; 551 + const struct ov08d10_link_freq_config link_freq_configs[2]; 552 + const struct ov08d10_mode sp_modes[3]; 553 + }; 554 + 555 + static const struct ov08d10_lane_cfg lane_cfg_2 = { 556 + { 557 + 720000000, 558 + 360000000, 559 + }, 560 + {{ 561 + .reg_list = { 562 + .num_of_regs = 563 + ARRAY_SIZE(mipi_data_rate_720mbps), 564 + .regs = mipi_data_rate_720mbps, 565 + } 566 + }, 567 + { 568 + .reg_list = { 569 + .num_of_regs = 570 + ARRAY_SIZE(mipi_data_rate_360mbps), 571 + .regs = mipi_data_rate_360mbps, 572 + } 573 + }}, 574 + {{ 575 + .width = 3280, 576 + .height = 2460, 577 + .hts = 1840, 578 + .vts_def = 2504, 579 + .vts_min = 2504, 580 + .reg_list = { 581 + .num_of_regs = ARRAY_SIZE(lane_2_mode_3280x2460), 582 + .regs = lane_2_mode_3280x2460, 583 + }, 584 + .link_freq_index = 0, 585 + .data_lanes = 2, 586 + }, 587 + { 588 + .width = 3264, 589 + .height = 2448, 590 + .hts = 1840, 591 + .vts_def = 2504, 592 + .vts_min = 2504, 593 + .reg_list = { 594 + .num_of_regs = ARRAY_SIZE(lane_2_mode_3264x2448), 595 + .regs = lane_2_mode_3264x2448, 596 + }, 597 + .link_freq_index = 0, 598 + .data_lanes = 2, 599 + }, 600 + { 601 + .width = 1632, 602 + .height = 1224, 603 + .hts = 1912, 604 + .vts_def = 3736, 605 + .vts_min = 3736, 606 + .reg_list = { 607 + .num_of_regs = ARRAY_SIZE(lane_2_mode_1632x1224), 608 + .regs = lane_2_mode_1632x1224, 609 + }, 610 + .link_freq_index = 1, 611 + .data_lanes = 2, 612 + }} 613 + }; 614 + 615 + static u32 ov08d10_get_format_code(struct ov08d10 *ov08d10) 616 + { 617 + static const u32 codes[2][2] = { 618 + { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10}, 619 + { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10}, 620 + }; 621 + 622 + return codes[ov08d10->vflip->val][ov08d10->hflip->val]; 623 + } 624 + 625 + static unsigned int ov08d10_modes_num(const struct ov08d10 *ov08d10) 626 + { 627 + unsigned int i, count = 0; 628 + 629 + for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->sp_modes); i++) { 630 + if (ov08d10->priv_lane->sp_modes[i].width == 0) 631 + break; 632 + count++; 633 + } 634 + 635 + return count; 636 + } 637 + 638 + static u64 to_rate(const s64 *link_freq_menu, 639 + u32 f_index, u8 nlanes) 640 + { 641 + u64 pixel_rate = link_freq_menu[f_index] * 2 * nlanes; 642 + 643 + do_div(pixel_rate, OV08D10_RGB_DEPTH); 644 + 645 + return pixel_rate; 646 + } 647 + 648 + static u64 to_pixels_per_line(const s64 *link_freq_menu, u32 hts, 649 + u32 f_index, u8 nlanes) 650 + { 651 + u64 ppl = hts * to_rate(link_freq_menu, f_index, nlanes); 652 + 653 + do_div(ppl, OV08D10_SCLK); 654 + 655 + return ppl; 656 + } 657 + 658 + static int ov08d10_write_reg_list(struct ov08d10 *ov08d10, 659 + const struct ov08d10_reg_list *r_list) 660 + { 661 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 662 + unsigned int i; 663 + int ret; 664 + 665 + for (i = 0; i < r_list->num_of_regs; i++) { 666 + ret = i2c_smbus_write_byte_data(client, r_list->regs[i].address, 667 + r_list->regs[i].val); 668 + if (ret) { 669 + dev_err_ratelimited(&client->dev, 670 + "failed to write reg 0x%2.2x. error = %d", 671 + r_list->regs[i].address, ret); 672 + return ret; 673 + } 674 + } 675 + 676 + return 0; 677 + } 678 + 679 + static int ov08d10_update_analog_gain(struct ov08d10 *ov08d10, u32 a_gain) 680 + { 681 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 682 + u8 val; 683 + int ret; 684 + 685 + val = ((a_gain >> 3) & 0xFF); 686 + /* CIS control registers */ 687 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 688 + if (ret < 0) 689 + return ret; 690 + 691 + /* update AGAIN */ 692 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_ANALOG_GAIN, val); 693 + if (ret < 0) 694 + return ret; 695 + 696 + return i2c_smbus_write_byte_data(client, 697 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 698 + } 699 + 700 + static int ov08d10_update_digital_gain(struct ov08d10 *ov08d10, u32 d_gain) 701 + { 702 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 703 + u8 val; 704 + int ret; 705 + 706 + d_gain = (d_gain >> 1); 707 + /* CIS control registers */ 708 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 709 + if (ret < 0) 710 + return ret; 711 + 712 + val = ((d_gain >> 8) & 0x3F); 713 + /* update DGAIN */ 714 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_C, val); 715 + if (ret < 0) 716 + return ret; 717 + 718 + val = d_gain & 0xFF; 719 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_F, val); 720 + if (ret < 0) 721 + return ret; 722 + 723 + return i2c_smbus_write_byte_data(client, 724 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 725 + } 726 + 727 + static int ov08d10_set_exposure(struct ov08d10 *ov08d10, u32 exposure) 728 + { 729 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 730 + u8 val; 731 + u8 hts_h, hts_l; 732 + u32 hts, cur_vts, exp_cal; 733 + int ret; 734 + 735 + cur_vts = ov08d10->cur_mode->vts_def; 736 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 737 + if (ret < 0) 738 + return ret; 739 + 740 + hts_h = i2c_smbus_read_byte_data(client, 0x37); 741 + hts_l = i2c_smbus_read_byte_data(client, 0x38); 742 + hts = ((hts_h << 8) | (hts_l)); 743 + exp_cal = 66 * OV08D10_ROWCLK / hts; 744 + exposure = exposure * exp_cal / (cur_vts - OV08D10_EXPOSURE_MAX_MARGIN); 745 + /* CIS control registers */ 746 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 747 + if (ret < 0) 748 + return ret; 749 + 750 + /* update exposure */ 751 + val = ((exposure >> 16) & 0xFF); 752 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_H, val); 753 + if (ret < 0) 754 + return ret; 755 + 756 + val = ((exposure >> 8) & 0xFF); 757 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_M, val); 758 + if (ret < 0) 759 + return ret; 760 + 761 + val = exposure & 0xFF; 762 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_L, val); 763 + if (ret < 0) 764 + return ret; 765 + 766 + return i2c_smbus_write_byte_data(client, 767 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 768 + } 769 + 770 + static int ov08d10_set_vblank(struct ov08d10 *ov08d10, u32 vblank) 771 + { 772 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 773 + u8 val; 774 + int ret; 775 + 776 + /* CIS control registers */ 777 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 778 + if (ret < 0) 779 + return ret; 780 + 781 + val = ((vblank >> 8) & 0xFF); 782 + /* update vblank */ 783 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_H, val); 784 + if (ret < 0) 785 + return ret; 786 + 787 + val = vblank & 0xFF; 788 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_L, val); 789 + if (ret < 0) 790 + return ret; 791 + 792 + return i2c_smbus_write_byte_data(client, 793 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 794 + } 795 + 796 + static int ov08d10_test_pattern(struct ov08d10 *ov08d10, u32 pattern) 797 + { 798 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 799 + u8 val; 800 + int ret; 801 + 802 + if (pattern) 803 + val = OV08D10_TEST_PATTERN_ENABLE; 804 + else 805 + val = OV08D10_TEST_PATTERN_DISABLE; 806 + 807 + /* CIS control registers */ 808 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 809 + if (ret < 0) 810 + return ret; 811 + 812 + ret = i2c_smbus_write_byte_data(client, 813 + OV08D10_REG_TEST_PATTERN, val); 814 + if (ret < 0) 815 + return ret; 816 + 817 + return i2c_smbus_write_byte_data(client, 818 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 819 + } 820 + 821 + static int ov08d10_set_ctrl_flip(struct ov08d10 *ov08d10, u32 ctrl_val) 822 + { 823 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 824 + u8 val; 825 + int ret; 826 + 827 + /* System control registers */ 828 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 829 + if (ret < 0) 830 + return ret; 831 + 832 + ret = i2c_smbus_read_byte_data(client, OV08D10_REG_FLIP_OPT); 833 + if (ret < 0) 834 + return ret; 835 + 836 + val = ret | (ctrl_val & OV08D10_REG_FLIP_MASK); 837 + 838 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 839 + if (ret < 0) 840 + return ret; 841 + 842 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_FLIP_OPT, val); 843 + 844 + if (ret < 0) 845 + return ret; 846 + 847 + return i2c_smbus_write_byte_data(client, 848 + OV08D10_REG_GLOBAL_EFFECTIVE, 0x01); 849 + } 850 + 851 + static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl) 852 + { 853 + struct ov08d10 *ov08d10 = container_of(ctrl->handler, 854 + struct ov08d10, ctrl_handler); 855 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 856 + s64 exposure_max; 857 + int ret; 858 + 859 + /* Propagate change of current control to all related controls */ 860 + if (ctrl->id == V4L2_CID_VBLANK) { 861 + /* Update max exposure while meeting expected vblanking */ 862 + exposure_max = ov08d10->cur_mode->height + ctrl->val - 863 + OV08D10_EXPOSURE_MAX_MARGIN; 864 + __v4l2_ctrl_modify_range(ov08d10->exposure, 865 + ov08d10->exposure->minimum, 866 + exposure_max, ov08d10->exposure->step, 867 + exposure_max); 868 + } 869 + 870 + /* V4L2 controls values will be applied only when power is already up */ 871 + if (!pm_runtime_get_if_in_use(&client->dev)) 872 + return 0; 873 + 874 + switch (ctrl->id) { 875 + case V4L2_CID_ANALOGUE_GAIN: 876 + ret = ov08d10_update_analog_gain(ov08d10, ctrl->val); 877 + break; 878 + 879 + case V4L2_CID_DIGITAL_GAIN: 880 + ret = ov08d10_update_digital_gain(ov08d10, ctrl->val); 881 + break; 882 + 883 + case V4L2_CID_EXPOSURE: 884 + ret = ov08d10_set_exposure(ov08d10, ctrl->val); 885 + break; 886 + 887 + case V4L2_CID_VBLANK: 888 + ret = ov08d10_set_vblank(ov08d10, ctrl->val); 889 + break; 890 + 891 + case V4L2_CID_TEST_PATTERN: 892 + ret = ov08d10_test_pattern(ov08d10, ctrl->val); 893 + break; 894 + 895 + case V4L2_CID_HFLIP: 896 + case V4L2_CID_VFLIP: 897 + ret = ov08d10_set_ctrl_flip(ov08d10, 898 + ov08d10->hflip->val | 899 + ov08d10->vflip->val << 1); 900 + break; 901 + 902 + default: 903 + ret = -EINVAL; 904 + break; 905 + } 906 + 907 + pm_runtime_put(&client->dev); 908 + 909 + return ret; 910 + } 911 + 912 + static const struct v4l2_ctrl_ops ov08d10_ctrl_ops = { 913 + .s_ctrl = ov08d10_set_ctrl, 914 + }; 915 + 916 + static int ov08d10_init_controls(struct ov08d10 *ov08d10) 917 + { 918 + struct v4l2_ctrl_handler *ctrl_hdlr; 919 + u8 link_freq_size; 920 + s64 exposure_max; 921 + s64 vblank_def; 922 + s64 vblank_min; 923 + s64 h_blank; 924 + s64 pixel_rate_max; 925 + const struct ov08d10_mode *mode; 926 + int ret; 927 + 928 + ctrl_hdlr = &ov08d10->ctrl_handler; 929 + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); 930 + if (ret) 931 + return ret; 932 + 933 + ctrl_hdlr->lock = &ov08d10->mutex; 934 + link_freq_size = ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu); 935 + ov08d10->link_freq = 936 + v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov08d10_ctrl_ops, 937 + V4L2_CID_LINK_FREQ, 938 + link_freq_size - 1, 939 + 0, 940 + ov08d10->priv_lane->link_freq_menu); 941 + if (ov08d10->link_freq) 942 + ov08d10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; 943 + 944 + pixel_rate_max = to_rate(ov08d10->priv_lane->link_freq_menu, 0, 945 + ov08d10->cur_mode->data_lanes); 946 + ov08d10->pixel_rate = 947 + v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 948 + V4L2_CID_PIXEL_RATE, 0, pixel_rate_max, 1, 949 + pixel_rate_max); 950 + 951 + mode = ov08d10->cur_mode; 952 + vblank_def = mode->vts_def - mode->height; 953 + vblank_min = mode->vts_min - mode->height; 954 + ov08d10->vblank = 955 + v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 956 + V4L2_CID_VBLANK, vblank_min, 957 + OV08D10_VTS_MAX - mode->height, 1, 958 + vblank_def); 959 + 960 + h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu, 961 + mode->hts, mode->link_freq_index, 962 + mode->data_lanes) - 963 + mode->width; 964 + ov08d10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 965 + V4L2_CID_HBLANK, h_blank, h_blank, 966 + 1, h_blank); 967 + if (ov08d10->hblank) 968 + ov08d10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; 969 + 970 + v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, 971 + OV08D10_ANAL_GAIN_MIN, OV08D10_ANAL_GAIN_MAX, 972 + OV08D10_ANAL_GAIN_STEP, OV08D10_ANAL_GAIN_MIN); 973 + 974 + v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_DIGITAL_GAIN, 975 + OV08D10_DGTL_GAIN_MIN, OV08D10_DGTL_GAIN_MAX, 976 + OV08D10_DGTL_GAIN_STEP, OV08D10_DGTL_GAIN_DEFAULT); 977 + 978 + exposure_max = mode->vts_def - OV08D10_EXPOSURE_MAX_MARGIN; 979 + ov08d10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 980 + V4L2_CID_EXPOSURE, 981 + OV08D10_EXPOSURE_MIN, 982 + exposure_max, 983 + OV08D10_EXPOSURE_STEP, 984 + exposure_max); 985 + 986 + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov08d10_ctrl_ops, 987 + V4L2_CID_TEST_PATTERN, 988 + ARRAY_SIZE(ov08d10_test_pattern_menu) - 1, 989 + 0, 0, ov08d10_test_pattern_menu); 990 + 991 + ov08d10->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 992 + V4L2_CID_HFLIP, 0, 1, 1, 0); 993 + ov08d10->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, 994 + V4L2_CID_VFLIP, 0, 1, 1, 0); 995 + if (ctrl_hdlr->error) 996 + return ctrl_hdlr->error; 997 + 998 + ov08d10->sd.ctrl_handler = ctrl_hdlr; 999 + 1000 + return 0; 1001 + } 1002 + 1003 + static void ov08d10_update_pad_format(struct ov08d10 *ov08d10, 1004 + const struct ov08d10_mode *mode, 1005 + struct v4l2_mbus_framefmt *fmt) 1006 + { 1007 + fmt->width = mode->width; 1008 + fmt->height = mode->height; 1009 + fmt->code = ov08d10_get_format_code(ov08d10); 1010 + fmt->field = V4L2_FIELD_NONE; 1011 + } 1012 + 1013 + static int ov08d10_start_streaming(struct ov08d10 *ov08d10) 1014 + { 1015 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 1016 + const struct ov08d10_reg_list *reg_list; 1017 + int link_freq_index, ret; 1018 + 1019 + link_freq_index = ov08d10->cur_mode->link_freq_index; 1020 + reg_list = 1021 + &ov08d10->priv_lane->link_freq_configs[link_freq_index].reg_list; 1022 + 1023 + /* soft reset */ 1024 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); 1025 + if (ret < 0) { 1026 + dev_err(&client->dev, "failed to reset sensor"); 1027 + return ret; 1028 + } 1029 + ret = i2c_smbus_write_byte_data(client, 0x20, 0x0e); 1030 + if (ret < 0) { 1031 + dev_err(&client->dev, "failed to reset sensor"); 1032 + return ret; 1033 + } 1034 + usleep_range(3000, 4000); 1035 + ret = i2c_smbus_write_byte_data(client, 0x20, 0x0b); 1036 + if (ret < 0) { 1037 + dev_err(&client->dev, "failed to reset sensor"); 1038 + return ret; 1039 + } 1040 + 1041 + /* update sensor setting */ 1042 + ret = ov08d10_write_reg_list(ov08d10, reg_list); 1043 + if (ret) { 1044 + dev_err(&client->dev, "failed to set plls"); 1045 + return ret; 1046 + } 1047 + 1048 + reg_list = &ov08d10->cur_mode->reg_list; 1049 + ret = ov08d10_write_reg_list(ov08d10, reg_list); 1050 + if (ret) { 1051 + dev_err(&client->dev, "failed to set mode"); 1052 + return ret; 1053 + } 1054 + 1055 + ret = __v4l2_ctrl_handler_setup(ov08d10->sd.ctrl_handler); 1056 + if (ret) 1057 + return ret; 1058 + 1059 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); 1060 + if (ret < 0) 1061 + return ret; 1062 + 1063 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT, 1064 + OV08D10_MODE_STREAMING); 1065 + if (ret < 0) 1066 + return ret; 1067 + 1068 + return i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 1069 + } 1070 + 1071 + static void ov08d10_stop_streaming(struct ov08d10 *ov08d10) 1072 + { 1073 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 1074 + int ret; 1075 + 1076 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); 1077 + if (ret < 0) { 1078 + dev_err(&client->dev, "failed to stop streaming"); 1079 + return; 1080 + } 1081 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT, 1082 + OV08D10_MODE_STANDBY); 1083 + if (ret < 0) { 1084 + dev_err(&client->dev, "failed to stop streaming"); 1085 + return; 1086 + } 1087 + 1088 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); 1089 + if (ret < 0) { 1090 + dev_err(&client->dev, "failed to stop streaming"); 1091 + return; 1092 + } 1093 + } 1094 + 1095 + static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) 1096 + { 1097 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1098 + struct i2c_client *client = v4l2_get_subdevdata(sd); 1099 + int ret = 0; 1100 + 1101 + if (ov08d10->streaming == enable) 1102 + return 0; 1103 + 1104 + mutex_lock(&ov08d10->mutex); 1105 + if (enable) { 1106 + ret = pm_runtime_resume_and_get(&client->dev); 1107 + if (ret < 0) { 1108 + mutex_unlock(&ov08d10->mutex); 1109 + return ret; 1110 + } 1111 + 1112 + ret = ov08d10_start_streaming(ov08d10); 1113 + if (ret) { 1114 + enable = 0; 1115 + ov08d10_stop_streaming(ov08d10); 1116 + pm_runtime_put(&client->dev); 1117 + } 1118 + } else { 1119 + ov08d10_stop_streaming(ov08d10); 1120 + pm_runtime_put(&client->dev); 1121 + } 1122 + 1123 + ov08d10->streaming = enable; 1124 + 1125 + /* vflip and hflip cannot change during streaming */ 1126 + __v4l2_ctrl_grab(ov08d10->vflip, enable); 1127 + __v4l2_ctrl_grab(ov08d10->hflip, enable); 1128 + 1129 + mutex_unlock(&ov08d10->mutex); 1130 + 1131 + return ret; 1132 + } 1133 + 1134 + static int __maybe_unused ov08d10_suspend(struct device *dev) 1135 + { 1136 + struct i2c_client *client = to_i2c_client(dev); 1137 + struct v4l2_subdev *sd = i2c_get_clientdata(client); 1138 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1139 + 1140 + mutex_lock(&ov08d10->mutex); 1141 + if (ov08d10->streaming) 1142 + ov08d10_stop_streaming(ov08d10); 1143 + 1144 + mutex_unlock(&ov08d10->mutex); 1145 + 1146 + return 0; 1147 + } 1148 + 1149 + static int __maybe_unused ov08d10_resume(struct device *dev) 1150 + { 1151 + struct i2c_client *client = to_i2c_client(dev); 1152 + struct v4l2_subdev *sd = i2c_get_clientdata(client); 1153 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1154 + int ret; 1155 + 1156 + mutex_lock(&ov08d10->mutex); 1157 + 1158 + if (ov08d10->streaming) { 1159 + ret = ov08d10_start_streaming(ov08d10); 1160 + if (ret) { 1161 + ov08d10->streaming = false; 1162 + ov08d10_stop_streaming(ov08d10); 1163 + mutex_unlock(&ov08d10->mutex); 1164 + return ret; 1165 + } 1166 + } 1167 + 1168 + mutex_unlock(&ov08d10->mutex); 1169 + 1170 + return 0; 1171 + } 1172 + 1173 + static int ov08d10_set_format(struct v4l2_subdev *sd, 1174 + struct v4l2_subdev_state *sd_state, 1175 + struct v4l2_subdev_format *fmt) 1176 + { 1177 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1178 + const struct ov08d10_mode *mode; 1179 + s32 vblank_def, h_blank; 1180 + s64 pixel_rate; 1181 + 1182 + mode = v4l2_find_nearest_size(ov08d10->priv_lane->sp_modes, 1183 + ov08d10->modes_size, 1184 + width, height, fmt->format.width, 1185 + fmt->format.height); 1186 + 1187 + mutex_lock(&ov08d10->mutex); 1188 + ov08d10_update_pad_format(ov08d10, mode, &fmt->format); 1189 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1190 + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = 1191 + fmt->format; 1192 + } else { 1193 + ov08d10->cur_mode = mode; 1194 + __v4l2_ctrl_s_ctrl(ov08d10->link_freq, mode->link_freq_index); 1195 + pixel_rate = to_rate(ov08d10->priv_lane->link_freq_menu, 1196 + mode->link_freq_index, 1197 + ov08d10->cur_mode->data_lanes); 1198 + __v4l2_ctrl_s_ctrl_int64(ov08d10->pixel_rate, pixel_rate); 1199 + 1200 + /* Update limits and set FPS to default */ 1201 + vblank_def = mode->vts_def - mode->height; 1202 + __v4l2_ctrl_modify_range(ov08d10->vblank, 1203 + mode->vts_min - mode->height, 1204 + OV08D10_VTS_MAX - mode->height, 1, 1205 + vblank_def); 1206 + __v4l2_ctrl_s_ctrl(ov08d10->vblank, vblank_def); 1207 + h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu, 1208 + mode->hts, 1209 + mode->link_freq_index, 1210 + ov08d10->cur_mode->data_lanes) 1211 + - mode->width; 1212 + __v4l2_ctrl_modify_range(ov08d10->hblank, h_blank, h_blank, 1, 1213 + h_blank); 1214 + } 1215 + 1216 + mutex_unlock(&ov08d10->mutex); 1217 + 1218 + return 0; 1219 + } 1220 + 1221 + static int ov08d10_get_format(struct v4l2_subdev *sd, 1222 + struct v4l2_subdev_state *sd_state, 1223 + struct v4l2_subdev_format *fmt) 1224 + { 1225 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1226 + 1227 + mutex_lock(&ov08d10->mutex); 1228 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) 1229 + fmt->format = *v4l2_subdev_get_try_format(&ov08d10->sd, 1230 + sd_state, 1231 + fmt->pad); 1232 + else 1233 + ov08d10_update_pad_format(ov08d10, ov08d10->cur_mode, 1234 + &fmt->format); 1235 + 1236 + mutex_unlock(&ov08d10->mutex); 1237 + 1238 + return 0; 1239 + } 1240 + 1241 + static int ov08d10_enum_mbus_code(struct v4l2_subdev *sd, 1242 + struct v4l2_subdev_state *sd_state, 1243 + struct v4l2_subdev_mbus_code_enum *code) 1244 + { 1245 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1246 + 1247 + if (code->index > 0) 1248 + return -EINVAL; 1249 + 1250 + mutex_lock(&ov08d10->mutex); 1251 + code->code = ov08d10_get_format_code(ov08d10); 1252 + mutex_unlock(&ov08d10->mutex); 1253 + 1254 + return 0; 1255 + } 1256 + 1257 + static int ov08d10_enum_frame_size(struct v4l2_subdev *sd, 1258 + struct v4l2_subdev_state *sd_state, 1259 + struct v4l2_subdev_frame_size_enum *fse) 1260 + { 1261 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1262 + 1263 + if (fse->index >= ov08d10->modes_size) 1264 + return -EINVAL; 1265 + 1266 + mutex_lock(&ov08d10->mutex); 1267 + if (fse->code != ov08d10_get_format_code(ov08d10)) 1268 + return -EINVAL; 1269 + mutex_unlock(&ov08d10->mutex); 1270 + 1271 + fse->min_width = ov08d10->priv_lane->sp_modes[fse->index].width; 1272 + fse->max_width = fse->min_width; 1273 + fse->min_height = ov08d10->priv_lane->sp_modes[fse->index].height; 1274 + fse->max_height = fse->min_height; 1275 + 1276 + return 0; 1277 + } 1278 + 1279 + static int ov08d10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1280 + { 1281 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1282 + 1283 + mutex_lock(&ov08d10->mutex); 1284 + ov08d10_update_pad_format(ov08d10, &ov08d10->priv_lane->sp_modes[0], 1285 + v4l2_subdev_get_try_format(sd, fh->state, 0)); 1286 + mutex_unlock(&ov08d10->mutex); 1287 + 1288 + return 0; 1289 + } 1290 + 1291 + static const struct v4l2_subdev_video_ops ov08d10_video_ops = { 1292 + .s_stream = ov08d10_set_stream, 1293 + }; 1294 + 1295 + static const struct v4l2_subdev_pad_ops ov08d10_pad_ops = { 1296 + .set_fmt = ov08d10_set_format, 1297 + .get_fmt = ov08d10_get_format, 1298 + .enum_mbus_code = ov08d10_enum_mbus_code, 1299 + .enum_frame_size = ov08d10_enum_frame_size, 1300 + }; 1301 + 1302 + static const struct v4l2_subdev_ops ov08d10_subdev_ops = { 1303 + .video = &ov08d10_video_ops, 1304 + .pad = &ov08d10_pad_ops, 1305 + }; 1306 + 1307 + static const struct v4l2_subdev_internal_ops ov08d10_internal_ops = { 1308 + .open = ov08d10_open, 1309 + }; 1310 + 1311 + static int ov08d10_identify_module(struct ov08d10 *ov08d10) 1312 + { 1313 + struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); 1314 + u32 val; 1315 + u16 chip_id; 1316 + int ret; 1317 + 1318 + /* System control registers */ 1319 + ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); 1320 + if (ret < 0) 1321 + return ret; 1322 + 1323 + /* Validate the chip ID */ 1324 + ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_0); 1325 + if (ret < 0) 1326 + return ret; 1327 + 1328 + val = ret << 8; 1329 + 1330 + ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_1); 1331 + if (ret < 0) 1332 + return ret; 1333 + 1334 + chip_id = val | ret; 1335 + 1336 + if ((chip_id & OV08D10_ID_MASK) != OV08D10_CHIP_ID) { 1337 + dev_err(&client->dev, "unexpected sensor id(0x%04x)\n", 1338 + chip_id); 1339 + return -EINVAL; 1340 + } 1341 + 1342 + return 0; 1343 + } 1344 + 1345 + static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10, struct device *dev) 1346 + { 1347 + struct fwnode_handle *ep; 1348 + struct fwnode_handle *fwnode = dev_fwnode(dev); 1349 + struct v4l2_fwnode_endpoint bus_cfg = { 1350 + .bus_type = V4L2_MBUS_CSI2_DPHY 1351 + }; 1352 + u32 xvclk_rate; 1353 + unsigned int i, j; 1354 + int ret; 1355 + 1356 + if (!fwnode) 1357 + return -ENXIO; 1358 + 1359 + ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate); 1360 + if (ret) 1361 + return ret; 1362 + 1363 + if (xvclk_rate != OV08D10_XVCLK_19_2) 1364 + dev_warn(dev, "external clock rate %u is unsupported", 1365 + xvclk_rate); 1366 + 1367 + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); 1368 + if (!ep) 1369 + return -ENXIO; 1370 + 1371 + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); 1372 + fwnode_handle_put(ep); 1373 + if (ret) 1374 + return ret; 1375 + 1376 + /* Get number of data lanes */ 1377 + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { 1378 + dev_err(dev, "number of CSI2 data lanes %d is not supported", 1379 + bus_cfg.bus.mipi_csi2.num_data_lanes); 1380 + ret = -EINVAL; 1381 + goto check_hwcfg_error; 1382 + } 1383 + 1384 + dev_dbg(dev, "Using %u data lanes\n", ov08d10->cur_mode->data_lanes); 1385 + 1386 + ov08d10->priv_lane = &lane_cfg_2; 1387 + ov08d10->modes_size = ov08d10_modes_num(ov08d10); 1388 + 1389 + if (!bus_cfg.nr_of_link_frequencies) { 1390 + dev_err(dev, "no link frequencies defined"); 1391 + ret = -EINVAL; 1392 + goto check_hwcfg_error; 1393 + } 1394 + 1395 + for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu); i++) { 1396 + for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) { 1397 + if (ov08d10->priv_lane->link_freq_menu[i] == 1398 + bus_cfg.link_frequencies[j]) 1399 + break; 1400 + } 1401 + 1402 + if (j == bus_cfg.nr_of_link_frequencies) { 1403 + dev_err(dev, "no link frequency %lld supported", 1404 + ov08d10->priv_lane->link_freq_menu[i]); 1405 + ret = -EINVAL; 1406 + goto check_hwcfg_error; 1407 + } 1408 + } 1409 + 1410 + check_hwcfg_error: 1411 + v4l2_fwnode_endpoint_free(&bus_cfg); 1412 + 1413 + return ret; 1414 + } 1415 + 1416 + static int ov08d10_remove(struct i2c_client *client) 1417 + { 1418 + struct v4l2_subdev *sd = i2c_get_clientdata(client); 1419 + struct ov08d10 *ov08d10 = to_ov08d10(sd); 1420 + 1421 + v4l2_async_unregister_subdev(sd); 1422 + media_entity_cleanup(&sd->entity); 1423 + v4l2_ctrl_handler_free(sd->ctrl_handler); 1424 + pm_runtime_disable(&client->dev); 1425 + mutex_destroy(&ov08d10->mutex); 1426 + 1427 + return 0; 1428 + } 1429 + 1430 + static int ov08d10_probe(struct i2c_client *client) 1431 + { 1432 + struct ov08d10 *ov08d10; 1433 + int ret; 1434 + 1435 + ov08d10 = devm_kzalloc(&client->dev, sizeof(*ov08d10), GFP_KERNEL); 1436 + if (!ov08d10) 1437 + return -ENOMEM; 1438 + 1439 + ret = ov08d10_get_hwcfg(ov08d10, &client->dev); 1440 + if (ret) { 1441 + dev_err(&client->dev, "failed to get HW configuration: %d", 1442 + ret); 1443 + return ret; 1444 + } 1445 + 1446 + v4l2_i2c_subdev_init(&ov08d10->sd, client, &ov08d10_subdev_ops); 1447 + 1448 + ret = ov08d10_identify_module(ov08d10); 1449 + if (ret) { 1450 + dev_err(&client->dev, "failed to find sensor: %d", ret); 1451 + return ret; 1452 + } 1453 + 1454 + mutex_init(&ov08d10->mutex); 1455 + ov08d10->cur_mode = &ov08d10->priv_lane->sp_modes[0]; 1456 + ret = ov08d10_init_controls(ov08d10); 1457 + if (ret) { 1458 + dev_err(&client->dev, "failed to init controls: %d", ret); 1459 + goto probe_error_v4l2_ctrl_handler_free; 1460 + } 1461 + 1462 + ov08d10->sd.internal_ops = &ov08d10_internal_ops; 1463 + ov08d10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1464 + ov08d10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 1465 + ov08d10->pad.flags = MEDIA_PAD_FL_SOURCE; 1466 + ret = media_entity_pads_init(&ov08d10->sd.entity, 1, &ov08d10->pad); 1467 + if (ret) { 1468 + dev_err(&client->dev, "failed to init entity pads: %d", ret); 1469 + goto probe_error_v4l2_ctrl_handler_free; 1470 + } 1471 + 1472 + ret = v4l2_async_register_subdev_sensor(&ov08d10->sd); 1473 + if (ret < 0) { 1474 + dev_err(&client->dev, "failed to register V4L2 subdev: %d", 1475 + ret); 1476 + goto probe_error_media_entity_cleanup; 1477 + } 1478 + 1479 + /* 1480 + * Device is already turned on by i2c-core with ACPI domain PM. 1481 + * Enable runtime PM and turn off the device. 1482 + */ 1483 + pm_runtime_set_active(&client->dev); 1484 + pm_runtime_enable(&client->dev); 1485 + pm_runtime_idle(&client->dev); 1486 + 1487 + return 0; 1488 + 1489 + probe_error_media_entity_cleanup: 1490 + media_entity_cleanup(&ov08d10->sd.entity); 1491 + 1492 + probe_error_v4l2_ctrl_handler_free: 1493 + v4l2_ctrl_handler_free(ov08d10->sd.ctrl_handler); 1494 + mutex_destroy(&ov08d10->mutex); 1495 + 1496 + return ret; 1497 + } 1498 + 1499 + static const struct dev_pm_ops ov08d10_pm_ops = { 1500 + SET_SYSTEM_SLEEP_PM_OPS(ov08d10_suspend, ov08d10_resume) 1501 + }; 1502 + 1503 + #ifdef CONFIG_ACPI 1504 + static const struct acpi_device_id ov08d10_acpi_ids[] = { 1505 + { "OVTI08D1" }, 1506 + { /* sentinel */ } 1507 + }; 1508 + 1509 + MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids); 1510 + #endif 1511 + 1512 + static struct i2c_driver ov08d10_i2c_driver = { 1513 + .driver = { 1514 + .name = "ov08d10", 1515 + .pm = &ov08d10_pm_ops, 1516 + .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), 1517 + }, 1518 + .probe_new = ov08d10_probe, 1519 + .remove = ov08d10_remove, 1520 + }; 1521 + 1522 + module_i2c_driver(ov08d10_i2c_driver); 1523 + 1524 + MODULE_AUTHOR("Su, Jimmy <jimmy.su@intel.com>"); 1525 + MODULE_DESCRIPTION("OmniVision ov08d10 sensor driver"); 1526 + MODULE_LICENSE("GPL v2");