1800 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2018 Intel Corporation3 4#include <linux/unaligned.h>5#include <linux/acpi.h>6#include <linux/i2c.h>7#include <linux/module.h>8#include <linux/pm_runtime.h>9#include <media/v4l2-ctrls.h>10#include <media/v4l2-device.h>11#include <media/v4l2-event.h>12#include <media/v4l2-fwnode.h>13 14#define IMX355_REG_MODE_SELECT 0x010015#define IMX355_MODE_STANDBY 0x0016#define IMX355_MODE_STREAMING 0x0117 18/* Chip ID */19#define IMX355_REG_CHIP_ID 0x001620#define IMX355_CHIP_ID 0x035521 22/* V_TIMING internal */23#define IMX355_REG_FLL 0x034024#define IMX355_FLL_MAX 0xffff25 26/* Exposure control */27#define IMX355_REG_EXPOSURE 0x020228#define IMX355_EXPOSURE_MIN 129#define IMX355_EXPOSURE_STEP 130#define IMX355_EXPOSURE_DEFAULT 0x028231 32/* Analog gain control */33#define IMX355_REG_ANALOG_GAIN 0x020434#define IMX355_ANA_GAIN_MIN 035#define IMX355_ANA_GAIN_MAX 96036#define IMX355_ANA_GAIN_STEP 137#define IMX355_ANA_GAIN_DEFAULT 038 39/* Digital gain control */40#define IMX355_REG_DPGA_USE_GLOBAL_GAIN 0x307041#define IMX355_REG_DIG_GAIN_GLOBAL 0x020e42#define IMX355_DGTL_GAIN_MIN 25643#define IMX355_DGTL_GAIN_MAX 409544#define IMX355_DGTL_GAIN_STEP 145#define IMX355_DGTL_GAIN_DEFAULT 25646 47/* Test Pattern Control */48#define IMX355_REG_TEST_PATTERN 0x060049#define IMX355_TEST_PATTERN_DISABLED 050#define IMX355_TEST_PATTERN_SOLID_COLOR 151#define IMX355_TEST_PATTERN_COLOR_BARS 252#define IMX355_TEST_PATTERN_GRAY_COLOR_BARS 353#define IMX355_TEST_PATTERN_PN9 454 55/* Flip Control */56#define IMX355_REG_ORIENTATION 0x010157 58/* default link frequency and external clock */59#define IMX355_LINK_FREQ_DEFAULT 360000000LL60#define IMX355_EXT_CLK 1920000061#define IMX355_LINK_FREQ_INDEX 062 63struct imx355_reg {64 u16 address;65 u8 val;66};67 68struct imx355_reg_list {69 u32 num_of_regs;70 const struct imx355_reg *regs;71};72 73/* Mode : resolution and related config&values */74struct imx355_mode {75 /* Frame width */76 u32 width;77 /* Frame height */78 u32 height;79 80 /* V-timing */81 u32 fll_def;82 u32 fll_min;83 84 /* H-timing */85 u32 llp;86 87 /* index of link frequency */88 u32 link_freq_index;89 90 /* Default register values */91 struct imx355_reg_list reg_list;92};93 94struct imx355_hwcfg {95 u32 ext_clk; /* sensor external clk */96 unsigned long link_freq_bitmap;97};98 99struct imx355 {100 struct v4l2_subdev sd;101 struct media_pad pad;102 103 struct v4l2_ctrl_handler ctrl_handler;104 /* V4L2 Controls */105 struct v4l2_ctrl *link_freq;106 struct v4l2_ctrl *pixel_rate;107 struct v4l2_ctrl *vblank;108 struct v4l2_ctrl *hblank;109 struct v4l2_ctrl *exposure;110 struct v4l2_ctrl *vflip;111 struct v4l2_ctrl *hflip;112 113 /* Current mode */114 const struct imx355_mode *cur_mode;115 116 struct imx355_hwcfg *hwcfg;117 118 /*119 * Mutex for serialized access:120 * Protect sensor set pad format and start/stop streaming safely.121 * Protect access to sensor v4l2 controls.122 */123 struct mutex mutex;124};125 126static const struct imx355_reg imx355_global_regs[] = {127 { 0x0136, 0x13 },128 { 0x0137, 0x33 },129 { 0x304e, 0x03 },130 { 0x4348, 0x16 },131 { 0x4350, 0x19 },132 { 0x4408, 0x0a },133 { 0x440c, 0x0b },134 { 0x4411, 0x5f },135 { 0x4412, 0x2c },136 { 0x4623, 0x00 },137 { 0x462c, 0x0f },138 { 0x462d, 0x00 },139 { 0x462e, 0x00 },140 { 0x4684, 0x54 },141 { 0x480a, 0x07 },142 { 0x4908, 0x07 },143 { 0x4909, 0x07 },144 { 0x490d, 0x0a },145 { 0x491e, 0x0f },146 { 0x4921, 0x06 },147 { 0x4923, 0x28 },148 { 0x4924, 0x28 },149 { 0x4925, 0x29 },150 { 0x4926, 0x29 },151 { 0x4927, 0x1f },152 { 0x4928, 0x20 },153 { 0x4929, 0x20 },154 { 0x492a, 0x20 },155 { 0x492c, 0x05 },156 { 0x492d, 0x06 },157 { 0x492e, 0x06 },158 { 0x492f, 0x06 },159 { 0x4930, 0x03 },160 { 0x4931, 0x04 },161 { 0x4932, 0x04 },162 { 0x4933, 0x05 },163 { 0x595e, 0x01 },164 { 0x5963, 0x01 },165 { 0x3030, 0x01 },166 { 0x3031, 0x01 },167 { 0x3045, 0x01 },168 { 0x4010, 0x00 },169 { 0x4011, 0x00 },170 { 0x4012, 0x00 },171 { 0x4013, 0x01 },172 { 0x68a8, 0xfe },173 { 0x68a9, 0xff },174 { 0x6888, 0x00 },175 { 0x6889, 0x00 },176 { 0x68b0, 0x00 },177 { 0x3058, 0x00 },178 { 0x305a, 0x00 },179};180 181static const struct imx355_reg_list imx355_global_setting = {182 .num_of_regs = ARRAY_SIZE(imx355_global_regs),183 .regs = imx355_global_regs,184};185 186static const struct imx355_reg mode_3268x2448_regs[] = {187 { 0x0112, 0x0a },188 { 0x0113, 0x0a },189 { 0x0114, 0x03 },190 { 0x0342, 0x0e },191 { 0x0343, 0x58 },192 { 0x0340, 0x0a },193 { 0x0341, 0x37 },194 { 0x0344, 0x00 },195 { 0x0345, 0x08 },196 { 0x0346, 0x00 },197 { 0x0347, 0x08 },198 { 0x0348, 0x0c },199 { 0x0349, 0xcb },200 { 0x034a, 0x09 },201 { 0x034b, 0x97 },202 { 0x0220, 0x00 },203 { 0x0222, 0x01 },204 { 0x0900, 0x00 },205 { 0x0901, 0x11 },206 { 0x0902, 0x00 },207 { 0x034c, 0x0c },208 { 0x034d, 0xc4 },209 { 0x034e, 0x09 },210 { 0x034f, 0x90 },211 { 0x0301, 0x05 },212 { 0x0303, 0x01 },213 { 0x0305, 0x02 },214 { 0x0306, 0x00 },215 { 0x0307, 0x78 },216 { 0x030b, 0x01 },217 { 0x030d, 0x02 },218 { 0x030e, 0x00 },219 { 0x030f, 0x4b },220 { 0x0310, 0x00 },221 { 0x0700, 0x00 },222 { 0x0701, 0x10 },223 { 0x0820, 0x0b },224 { 0x0821, 0x40 },225 { 0x3088, 0x04 },226 { 0x6813, 0x02 },227 { 0x6835, 0x07 },228 { 0x6836, 0x01 },229 { 0x6837, 0x04 },230 { 0x684d, 0x07 },231 { 0x684e, 0x01 },232 { 0x684f, 0x04 },233};234 235static const struct imx355_reg mode_3264x2448_regs[] = {236 { 0x0112, 0x0a },237 { 0x0113, 0x0a },238 { 0x0114, 0x03 },239 { 0x0342, 0x0e },240 { 0x0343, 0x58 },241 { 0x0340, 0x0a },242 { 0x0341, 0x37 },243 { 0x0344, 0x00 },244 { 0x0345, 0x08 },245 { 0x0346, 0x00 },246 { 0x0347, 0x08 },247 { 0x0348, 0x0c },248 { 0x0349, 0xc7 },249 { 0x034a, 0x09 },250 { 0x034b, 0x97 },251 { 0x0220, 0x00 },252 { 0x0222, 0x01 },253 { 0x0900, 0x00 },254 { 0x0901, 0x11 },255 { 0x0902, 0x00 },256 { 0x034c, 0x0c },257 { 0x034d, 0xc0 },258 { 0x034e, 0x09 },259 { 0x034f, 0x90 },260 { 0x0301, 0x05 },261 { 0x0303, 0x01 },262 { 0x0305, 0x02 },263 { 0x0306, 0x00 },264 { 0x0307, 0x78 },265 { 0x030b, 0x01 },266 { 0x030d, 0x02 },267 { 0x030e, 0x00 },268 { 0x030f, 0x4b },269 { 0x0310, 0x00 },270 { 0x0700, 0x00 },271 { 0x0701, 0x10 },272 { 0x0820, 0x0b },273 { 0x0821, 0x40 },274 { 0x3088, 0x04 },275 { 0x6813, 0x02 },276 { 0x6835, 0x07 },277 { 0x6836, 0x01 },278 { 0x6837, 0x04 },279 { 0x684d, 0x07 },280 { 0x684e, 0x01 },281 { 0x684f, 0x04 },282};283 284static const struct imx355_reg mode_3280x2464_regs[] = {285 { 0x0112, 0x0a },286 { 0x0113, 0x0a },287 { 0x0114, 0x03 },288 { 0x0342, 0x0e },289 { 0x0343, 0x58 },290 { 0x0340, 0x0a },291 { 0x0341, 0x37 },292 { 0x0344, 0x00 },293 { 0x0345, 0x00 },294 { 0x0346, 0x00 },295 { 0x0347, 0x00 },296 { 0x0348, 0x0c },297 { 0x0349, 0xcf },298 { 0x034a, 0x09 },299 { 0x034b, 0x9f },300 { 0x0220, 0x00 },301 { 0x0222, 0x01 },302 { 0x0900, 0x00 },303 { 0x0901, 0x11 },304 { 0x0902, 0x00 },305 { 0x034c, 0x0c },306 { 0x034d, 0xd0 },307 { 0x034e, 0x09 },308 { 0x034f, 0xa0 },309 { 0x0301, 0x05 },310 { 0x0303, 0x01 },311 { 0x0305, 0x02 },312 { 0x0306, 0x00 },313 { 0x0307, 0x78 },314 { 0x030b, 0x01 },315 { 0x030d, 0x02 },316 { 0x030e, 0x00 },317 { 0x030f, 0x4b },318 { 0x0310, 0x00 },319 { 0x0700, 0x00 },320 { 0x0701, 0x10 },321 { 0x0820, 0x0b },322 { 0x0821, 0x40 },323 { 0x3088, 0x04 },324 { 0x6813, 0x02 },325 { 0x6835, 0x07 },326 { 0x6836, 0x01 },327 { 0x6837, 0x04 },328 { 0x684d, 0x07 },329 { 0x684e, 0x01 },330 { 0x684f, 0x04 },331};332 333static const struct imx355_reg mode_1940x1096_regs[] = {334 { 0x0112, 0x0a },335 { 0x0113, 0x0a },336 { 0x0114, 0x03 },337 { 0x0342, 0x0e },338 { 0x0343, 0x58 },339 { 0x0340, 0x05 },340 { 0x0341, 0x1a },341 { 0x0344, 0x02 },342 { 0x0345, 0xa0 },343 { 0x0346, 0x02 },344 { 0x0347, 0xac },345 { 0x0348, 0x0a },346 { 0x0349, 0x33 },347 { 0x034a, 0x06 },348 { 0x034b, 0xf3 },349 { 0x0220, 0x00 },350 { 0x0222, 0x01 },351 { 0x0900, 0x00 },352 { 0x0901, 0x11 },353 { 0x0902, 0x00 },354 { 0x034c, 0x07 },355 { 0x034d, 0x94 },356 { 0x034e, 0x04 },357 { 0x034f, 0x48 },358 { 0x0301, 0x05 },359 { 0x0303, 0x01 },360 { 0x0305, 0x02 },361 { 0x0306, 0x00 },362 { 0x0307, 0x78 },363 { 0x030b, 0x01 },364 { 0x030d, 0x02 },365 { 0x030e, 0x00 },366 { 0x030f, 0x4b },367 { 0x0310, 0x00 },368 { 0x0700, 0x00 },369 { 0x0701, 0x10 },370 { 0x0820, 0x0b },371 { 0x0821, 0x40 },372 { 0x3088, 0x04 },373 { 0x6813, 0x02 },374 { 0x6835, 0x07 },375 { 0x6836, 0x01 },376 { 0x6837, 0x04 },377 { 0x684d, 0x07 },378 { 0x684e, 0x01 },379 { 0x684f, 0x04 },380};381 382static const struct imx355_reg mode_1936x1096_regs[] = {383 { 0x0112, 0x0a },384 { 0x0113, 0x0a },385 { 0x0114, 0x03 },386 { 0x0342, 0x0e },387 { 0x0343, 0x58 },388 { 0x0340, 0x05 },389 { 0x0341, 0x1a },390 { 0x0344, 0x02 },391 { 0x0345, 0xa0 },392 { 0x0346, 0x02 },393 { 0x0347, 0xac },394 { 0x0348, 0x0a },395 { 0x0349, 0x2f },396 { 0x034a, 0x06 },397 { 0x034b, 0xf3 },398 { 0x0220, 0x00 },399 { 0x0222, 0x01 },400 { 0x0900, 0x00 },401 { 0x0901, 0x11 },402 { 0x0902, 0x00 },403 { 0x034c, 0x07 },404 { 0x034d, 0x90 },405 { 0x034e, 0x04 },406 { 0x034f, 0x48 },407 { 0x0301, 0x05 },408 { 0x0303, 0x01 },409 { 0x0305, 0x02 },410 { 0x0306, 0x00 },411 { 0x0307, 0x78 },412 { 0x030b, 0x01 },413 { 0x030d, 0x02 },414 { 0x030e, 0x00 },415 { 0x030f, 0x4b },416 { 0x0310, 0x00 },417 { 0x0700, 0x00 },418 { 0x0701, 0x10 },419 { 0x0820, 0x0b },420 { 0x0821, 0x40 },421 { 0x3088, 0x04 },422 { 0x6813, 0x02 },423 { 0x6835, 0x07 },424 { 0x6836, 0x01 },425 { 0x6837, 0x04 },426 { 0x684d, 0x07 },427 { 0x684e, 0x01 },428 { 0x684f, 0x04 },429};430 431static const struct imx355_reg mode_1924x1080_regs[] = {432 { 0x0112, 0x0a },433 { 0x0113, 0x0a },434 { 0x0114, 0x03 },435 { 0x0342, 0x0e },436 { 0x0343, 0x58 },437 { 0x0340, 0x05 },438 { 0x0341, 0x1a },439 { 0x0344, 0x02 },440 { 0x0345, 0xa8 },441 { 0x0346, 0x02 },442 { 0x0347, 0xb4 },443 { 0x0348, 0x0a },444 { 0x0349, 0x2b },445 { 0x034a, 0x06 },446 { 0x034b, 0xeb },447 { 0x0220, 0x00 },448 { 0x0222, 0x01 },449 { 0x0900, 0x00 },450 { 0x0901, 0x11 },451 { 0x0902, 0x00 },452 { 0x034c, 0x07 },453 { 0x034d, 0x84 },454 { 0x034e, 0x04 },455 { 0x034f, 0x38 },456 { 0x0301, 0x05 },457 { 0x0303, 0x01 },458 { 0x0305, 0x02 },459 { 0x0306, 0x00 },460 { 0x0307, 0x78 },461 { 0x030b, 0x01 },462 { 0x030d, 0x02 },463 { 0x030e, 0x00 },464 { 0x030f, 0x4b },465 { 0x0310, 0x00 },466 { 0x0700, 0x00 },467 { 0x0701, 0x10 },468 { 0x0820, 0x0b },469 { 0x0821, 0x40 },470 { 0x3088, 0x04 },471 { 0x6813, 0x02 },472 { 0x6835, 0x07 },473 { 0x6836, 0x01 },474 { 0x6837, 0x04 },475 { 0x684d, 0x07 },476 { 0x684e, 0x01 },477 { 0x684f, 0x04 },478};479 480static const struct imx355_reg mode_1920x1080_regs[] = {481 { 0x0112, 0x0a },482 { 0x0113, 0x0a },483 { 0x0114, 0x03 },484 { 0x0342, 0x0e },485 { 0x0343, 0x58 },486 { 0x0340, 0x05 },487 { 0x0341, 0x1a },488 { 0x0344, 0x02 },489 { 0x0345, 0xa8 },490 { 0x0346, 0x02 },491 { 0x0347, 0xb4 },492 { 0x0348, 0x0a },493 { 0x0349, 0x27 },494 { 0x034a, 0x06 },495 { 0x034b, 0xeb },496 { 0x0220, 0x00 },497 { 0x0222, 0x01 },498 { 0x0900, 0x00 },499 { 0x0901, 0x11 },500 { 0x0902, 0x00 },501 { 0x034c, 0x07 },502 { 0x034d, 0x80 },503 { 0x034e, 0x04 },504 { 0x034f, 0x38 },505 { 0x0301, 0x05 },506 { 0x0303, 0x01 },507 { 0x0305, 0x02 },508 { 0x0306, 0x00 },509 { 0x0307, 0x78 },510 { 0x030b, 0x01 },511 { 0x030d, 0x02 },512 { 0x030e, 0x00 },513 { 0x030f, 0x4b },514 { 0x0310, 0x00 },515 { 0x0700, 0x00 },516 { 0x0701, 0x10 },517 { 0x0820, 0x0b },518 { 0x0821, 0x40 },519 { 0x3088, 0x04 },520 { 0x6813, 0x02 },521 { 0x6835, 0x07 },522 { 0x6836, 0x01 },523 { 0x6837, 0x04 },524 { 0x684d, 0x07 },525 { 0x684e, 0x01 },526 { 0x684f, 0x04 },527};528 529static const struct imx355_reg mode_1640x1232_regs[] = {530 { 0x0112, 0x0a },531 { 0x0113, 0x0a },532 { 0x0114, 0x03 },533 { 0x0342, 0x07 },534 { 0x0343, 0x2c },535 { 0x0340, 0x05 },536 { 0x0341, 0x1a },537 { 0x0344, 0x00 },538 { 0x0345, 0x00 },539 { 0x0346, 0x00 },540 { 0x0347, 0x00 },541 { 0x0348, 0x0c },542 { 0x0349, 0xcf },543 { 0x034a, 0x09 },544 { 0x034b, 0x9f },545 { 0x0220, 0x00 },546 { 0x0222, 0x01 },547 { 0x0900, 0x01 },548 { 0x0901, 0x22 },549 { 0x0902, 0x00 },550 { 0x034c, 0x06 },551 { 0x034d, 0x68 },552 { 0x034e, 0x04 },553 { 0x034f, 0xd0 },554 { 0x0301, 0x05 },555 { 0x0303, 0x01 },556 { 0x0305, 0x02 },557 { 0x0306, 0x00 },558 { 0x0307, 0x78 },559 { 0x030b, 0x01 },560 { 0x030d, 0x02 },561 { 0x030e, 0x00 },562 { 0x030f, 0x4b },563 { 0x0310, 0x00 },564 { 0x0700, 0x00 },565 { 0x0701, 0x10 },566 { 0x0820, 0x0b },567 { 0x0821, 0x40 },568 { 0x3088, 0x04 },569 { 0x6813, 0x02 },570 { 0x6835, 0x07 },571 { 0x6836, 0x01 },572 { 0x6837, 0x04 },573 { 0x684d, 0x07 },574 { 0x684e, 0x01 },575 { 0x684f, 0x04 },576};577 578static const struct imx355_reg mode_1640x922_regs[] = {579 { 0x0112, 0x0a },580 { 0x0113, 0x0a },581 { 0x0114, 0x03 },582 { 0x0342, 0x07 },583 { 0x0343, 0x2c },584 { 0x0340, 0x05 },585 { 0x0341, 0x1a },586 { 0x0344, 0x00 },587 { 0x0345, 0x00 },588 { 0x0346, 0x01 },589 { 0x0347, 0x30 },590 { 0x0348, 0x0c },591 { 0x0349, 0xcf },592 { 0x034a, 0x08 },593 { 0x034b, 0x63 },594 { 0x0220, 0x00 },595 { 0x0222, 0x01 },596 { 0x0900, 0x01 },597 { 0x0901, 0x22 },598 { 0x0902, 0x00 },599 { 0x034c, 0x06 },600 { 0x034d, 0x68 },601 { 0x034e, 0x03 },602 { 0x034f, 0x9a },603 { 0x0301, 0x05 },604 { 0x0303, 0x01 },605 { 0x0305, 0x02 },606 { 0x0306, 0x00 },607 { 0x0307, 0x78 },608 { 0x030b, 0x01 },609 { 0x030d, 0x02 },610 { 0x030e, 0x00 },611 { 0x030f, 0x4b },612 { 0x0310, 0x00 },613 { 0x0700, 0x00 },614 { 0x0701, 0x10 },615 { 0x0820, 0x0b },616 { 0x0821, 0x40 },617 { 0x3088, 0x04 },618 { 0x6813, 0x02 },619 { 0x6835, 0x07 },620 { 0x6836, 0x01 },621 { 0x6837, 0x04 },622 { 0x684d, 0x07 },623 { 0x684e, 0x01 },624 { 0x684f, 0x04 },625};626 627static const struct imx355_reg mode_1300x736_regs[] = {628 { 0x0112, 0x0a },629 { 0x0113, 0x0a },630 { 0x0114, 0x03 },631 { 0x0342, 0x07 },632 { 0x0343, 0x2c },633 { 0x0340, 0x05 },634 { 0x0341, 0x1a },635 { 0x0344, 0x01 },636 { 0x0345, 0x58 },637 { 0x0346, 0x01 },638 { 0x0347, 0xf0 },639 { 0x0348, 0x0b },640 { 0x0349, 0x7f },641 { 0x034a, 0x07 },642 { 0x034b, 0xaf },643 { 0x0220, 0x00 },644 { 0x0222, 0x01 },645 { 0x0900, 0x01 },646 { 0x0901, 0x22 },647 { 0x0902, 0x00 },648 { 0x034c, 0x05 },649 { 0x034d, 0x14 },650 { 0x034e, 0x02 },651 { 0x034f, 0xe0 },652 { 0x0301, 0x05 },653 { 0x0303, 0x01 },654 { 0x0305, 0x02 },655 { 0x0306, 0x00 },656 { 0x0307, 0x78 },657 { 0x030b, 0x01 },658 { 0x030d, 0x02 },659 { 0x030e, 0x00 },660 { 0x030f, 0x4b },661 { 0x0310, 0x00 },662 { 0x0700, 0x00 },663 { 0x0701, 0x10 },664 { 0x0820, 0x0b },665 { 0x0821, 0x40 },666 { 0x3088, 0x04 },667 { 0x6813, 0x02 },668 { 0x6835, 0x07 },669 { 0x6836, 0x01 },670 { 0x6837, 0x04 },671 { 0x684d, 0x07 },672 { 0x684e, 0x01 },673 { 0x684f, 0x04 },674};675 676static const struct imx355_reg mode_1296x736_regs[] = {677 { 0x0112, 0x0a },678 { 0x0113, 0x0a },679 { 0x0114, 0x03 },680 { 0x0342, 0x07 },681 { 0x0343, 0x2c },682 { 0x0340, 0x05 },683 { 0x0341, 0x1a },684 { 0x0344, 0x01 },685 { 0x0345, 0x58 },686 { 0x0346, 0x01 },687 { 0x0347, 0xf0 },688 { 0x0348, 0x0b },689 { 0x0349, 0x77 },690 { 0x034a, 0x07 },691 { 0x034b, 0xaf },692 { 0x0220, 0x00 },693 { 0x0222, 0x01 },694 { 0x0900, 0x01 },695 { 0x0901, 0x22 },696 { 0x0902, 0x00 },697 { 0x034c, 0x05 },698 { 0x034d, 0x10 },699 { 0x034e, 0x02 },700 { 0x034f, 0xe0 },701 { 0x0301, 0x05 },702 { 0x0303, 0x01 },703 { 0x0305, 0x02 },704 { 0x0306, 0x00 },705 { 0x0307, 0x78 },706 { 0x030b, 0x01 },707 { 0x030d, 0x02 },708 { 0x030e, 0x00 },709 { 0x030f, 0x4b },710 { 0x0310, 0x00 },711 { 0x0700, 0x00 },712 { 0x0701, 0x10 },713 { 0x0820, 0x0b },714 { 0x0821, 0x40 },715 { 0x3088, 0x04 },716 { 0x6813, 0x02 },717 { 0x6835, 0x07 },718 { 0x6836, 0x01 },719 { 0x6837, 0x04 },720 { 0x684d, 0x07 },721 { 0x684e, 0x01 },722 { 0x684f, 0x04 },723};724 725static const struct imx355_reg mode_1284x720_regs[] = {726 { 0x0112, 0x0a },727 { 0x0113, 0x0a },728 { 0x0114, 0x03 },729 { 0x0342, 0x07 },730 { 0x0343, 0x2c },731 { 0x0340, 0x05 },732 { 0x0341, 0x1a },733 { 0x0344, 0x01 },734 { 0x0345, 0x68 },735 { 0x0346, 0x02 },736 { 0x0347, 0x00 },737 { 0x0348, 0x0b },738 { 0x0349, 0x6f },739 { 0x034a, 0x07 },740 { 0x034b, 0x9f },741 { 0x0220, 0x00 },742 { 0x0222, 0x01 },743 { 0x0900, 0x01 },744 { 0x0901, 0x22 },745 { 0x0902, 0x00 },746 { 0x034c, 0x05 },747 { 0x034d, 0x04 },748 { 0x034e, 0x02 },749 { 0x034f, 0xd0 },750 { 0x0301, 0x05 },751 { 0x0303, 0x01 },752 { 0x0305, 0x02 },753 { 0x0306, 0x00 },754 { 0x0307, 0x78 },755 { 0x030b, 0x01 },756 { 0x030d, 0x02 },757 { 0x030e, 0x00 },758 { 0x030f, 0x4b },759 { 0x0310, 0x00 },760 { 0x0700, 0x00 },761 { 0x0701, 0x10 },762 { 0x0820, 0x0b },763 { 0x0821, 0x40 },764 { 0x3088, 0x04 },765 { 0x6813, 0x02 },766 { 0x6835, 0x07 },767 { 0x6836, 0x01 },768 { 0x6837, 0x04 },769 { 0x684d, 0x07 },770 { 0x684e, 0x01 },771 { 0x684f, 0x04 },772};773 774static const struct imx355_reg mode_1280x720_regs[] = {775 { 0x0112, 0x0a },776 { 0x0113, 0x0a },777 { 0x0114, 0x03 },778 { 0x0342, 0x07 },779 { 0x0343, 0x2c },780 { 0x0340, 0x05 },781 { 0x0341, 0x1a },782 { 0x0344, 0x01 },783 { 0x0345, 0x68 },784 { 0x0346, 0x02 },785 { 0x0347, 0x00 },786 { 0x0348, 0x0b },787 { 0x0349, 0x67 },788 { 0x034a, 0x07 },789 { 0x034b, 0x9f },790 { 0x0220, 0x00 },791 { 0x0222, 0x01 },792 { 0x0900, 0x01 },793 { 0x0901, 0x22 },794 { 0x0902, 0x00 },795 { 0x034c, 0x05 },796 { 0x034d, 0x00 },797 { 0x034e, 0x02 },798 { 0x034f, 0xd0 },799 { 0x0301, 0x05 },800 { 0x0303, 0x01 },801 { 0x0305, 0x02 },802 { 0x0306, 0x00 },803 { 0x0307, 0x78 },804 { 0x030b, 0x01 },805 { 0x030d, 0x02 },806 { 0x030e, 0x00 },807 { 0x030f, 0x4b },808 { 0x0310, 0x00 },809 { 0x0700, 0x00 },810 { 0x0701, 0x10 },811 { 0x0820, 0x0b },812 { 0x0821, 0x40 },813 { 0x3088, 0x04 },814 { 0x6813, 0x02 },815 { 0x6835, 0x07 },816 { 0x6836, 0x01 },817 { 0x6837, 0x04 },818 { 0x684d, 0x07 },819 { 0x684e, 0x01 },820 { 0x684f, 0x04 },821};822 823static const struct imx355_reg mode_820x616_regs[] = {824 { 0x0112, 0x0a },825 { 0x0113, 0x0a },826 { 0x0114, 0x03 },827 { 0x0342, 0x0e },828 { 0x0343, 0x58 },829 { 0x0340, 0x02 },830 { 0x0341, 0x8c },831 { 0x0344, 0x00 },832 { 0x0345, 0x00 },833 { 0x0346, 0x00 },834 { 0x0347, 0x00 },835 { 0x0348, 0x0c },836 { 0x0349, 0xcf },837 { 0x034a, 0x09 },838 { 0x034b, 0x9f },839 { 0x0220, 0x00 },840 { 0x0222, 0x01 },841 { 0x0900, 0x01 },842 { 0x0901, 0x44 },843 { 0x0902, 0x00 },844 { 0x034c, 0x03 },845 { 0x034d, 0x34 },846 { 0x034e, 0x02 },847 { 0x034f, 0x68 },848 { 0x0301, 0x05 },849 { 0x0303, 0x01 },850 { 0x0305, 0x02 },851 { 0x0306, 0x00 },852 { 0x0307, 0x78 },853 { 0x030b, 0x01 },854 { 0x030d, 0x02 },855 { 0x030e, 0x00 },856 { 0x030f, 0x4b },857 { 0x0310, 0x00 },858 { 0x0700, 0x02 },859 { 0x0701, 0x78 },860 { 0x0820, 0x0b },861 { 0x0821, 0x40 },862 { 0x3088, 0x04 },863 { 0x6813, 0x02 },864 { 0x6835, 0x07 },865 { 0x6836, 0x01 },866 { 0x6837, 0x04 },867 { 0x684d, 0x07 },868 { 0x684e, 0x01 },869 { 0x684f, 0x04 },870};871 872static const char * const imx355_test_pattern_menu[] = {873 "Disabled",874 "Solid Colour",875 "Eight Vertical Colour Bars",876 "Colour Bars With Fade to Grey",877 "Pseudorandom Sequence (PN9)",878};879 880/*881 * When adding more than the one below, make sure the disallowed ones will882 * actually be disabled in the LINK_FREQ control.883 */884static const s64 link_freq_menu_items[] = {885 IMX355_LINK_FREQ_DEFAULT,886};887 888/* Mode configs */889static const struct imx355_mode supported_modes[] = {890 {891 .width = 3280,892 .height = 2464,893 .fll_def = 2615,894 .fll_min = 2615,895 .llp = 3672,896 .link_freq_index = IMX355_LINK_FREQ_INDEX,897 .reg_list = {898 .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),899 .regs = mode_3280x2464_regs,900 },901 },902 {903 .width = 3268,904 .height = 2448,905 .fll_def = 2615,906 .fll_min = 2615,907 .llp = 3672,908 .link_freq_index = IMX355_LINK_FREQ_INDEX,909 .reg_list = {910 .num_of_regs = ARRAY_SIZE(mode_3268x2448_regs),911 .regs = mode_3268x2448_regs,912 },913 },914 {915 .width = 3264,916 .height = 2448,917 .fll_def = 2615,918 .fll_min = 2615,919 .llp = 3672,920 .link_freq_index = IMX355_LINK_FREQ_INDEX,921 .reg_list = {922 .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),923 .regs = mode_3264x2448_regs,924 },925 },926 {927 .width = 1940,928 .height = 1096,929 .fll_def = 1306,930 .fll_min = 1306,931 .llp = 3672,932 .link_freq_index = IMX355_LINK_FREQ_INDEX,933 .reg_list = {934 .num_of_regs = ARRAY_SIZE(mode_1940x1096_regs),935 .regs = mode_1940x1096_regs,936 },937 },938 {939 .width = 1936,940 .height = 1096,941 .fll_def = 1306,942 .fll_min = 1306,943 .llp = 3672,944 .link_freq_index = IMX355_LINK_FREQ_INDEX,945 .reg_list = {946 .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),947 .regs = mode_1936x1096_regs,948 },949 },950 {951 .width = 1924,952 .height = 1080,953 .fll_def = 1306,954 .fll_min = 1306,955 .llp = 3672,956 .link_freq_index = IMX355_LINK_FREQ_INDEX,957 .reg_list = {958 .num_of_regs = ARRAY_SIZE(mode_1924x1080_regs),959 .regs = mode_1924x1080_regs,960 },961 },962 {963 .width = 1920,964 .height = 1080,965 .fll_def = 1306,966 .fll_min = 1306,967 .llp = 3672,968 .link_freq_index = IMX355_LINK_FREQ_INDEX,969 .reg_list = {970 .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),971 .regs = mode_1920x1080_regs,972 },973 },974 {975 .width = 1640,976 .height = 1232,977 .fll_def = 1306,978 .fll_min = 1306,979 .llp = 1836,980 .link_freq_index = IMX355_LINK_FREQ_INDEX,981 .reg_list = {982 .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),983 .regs = mode_1640x1232_regs,984 },985 },986 {987 .width = 1640,988 .height = 922,989 .fll_def = 1306,990 .fll_min = 1306,991 .llp = 1836,992 .link_freq_index = IMX355_LINK_FREQ_INDEX,993 .reg_list = {994 .num_of_regs = ARRAY_SIZE(mode_1640x922_regs),995 .regs = mode_1640x922_regs,996 },997 },998 {999 .width = 1300,1000 .height = 736,1001 .fll_def = 1306,1002 .fll_min = 1306,1003 .llp = 1836,1004 .link_freq_index = IMX355_LINK_FREQ_INDEX,1005 .reg_list = {1006 .num_of_regs = ARRAY_SIZE(mode_1300x736_regs),1007 .regs = mode_1300x736_regs,1008 },1009 },1010 {1011 .width = 1296,1012 .height = 736,1013 .fll_def = 1306,1014 .fll_min = 1306,1015 .llp = 1836,1016 .link_freq_index = IMX355_LINK_FREQ_INDEX,1017 .reg_list = {1018 .num_of_regs = ARRAY_SIZE(mode_1296x736_regs),1019 .regs = mode_1296x736_regs,1020 },1021 },1022 {1023 .width = 1284,1024 .height = 720,1025 .fll_def = 1306,1026 .fll_min = 1306,1027 .llp = 1836,1028 .link_freq_index = IMX355_LINK_FREQ_INDEX,1029 .reg_list = {1030 .num_of_regs = ARRAY_SIZE(mode_1284x720_regs),1031 .regs = mode_1284x720_regs,1032 },1033 },1034 {1035 .width = 1280,1036 .height = 720,1037 .fll_def = 1306,1038 .fll_min = 1306,1039 .llp = 1836,1040 .link_freq_index = IMX355_LINK_FREQ_INDEX,1041 .reg_list = {1042 .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),1043 .regs = mode_1280x720_regs,1044 },1045 },1046 {1047 .width = 820,1048 .height = 616,1049 .fll_def = 652,1050 .fll_min = 652,1051 .llp = 3672,1052 .link_freq_index = IMX355_LINK_FREQ_INDEX,1053 .reg_list = {1054 .num_of_regs = ARRAY_SIZE(mode_820x616_regs),1055 .regs = mode_820x616_regs,1056 },1057 },1058};1059 1060static inline struct imx355 *to_imx355(struct v4l2_subdev *_sd)1061{1062 return container_of(_sd, struct imx355, sd);1063}1064 1065/* Get bayer order based on flip setting. */1066static u32 imx355_get_format_code(struct imx355 *imx355)1067{1068 /*1069 * Only one bayer order is supported.1070 * It depends on the flip settings.1071 */1072 u32 code;1073 static const u32 codes[2][2] = {1074 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },1075 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },1076 };1077 1078 lockdep_assert_held(&imx355->mutex);1079 code = codes[imx355->vflip->val][imx355->hflip->val];1080 1081 return code;1082}1083 1084/* Read registers up to 4 at a time */1085static int imx355_read_reg(struct imx355 *imx355, u16 reg, u32 len, u32 *val)1086{1087 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1088 struct i2c_msg msgs[2];1089 u8 addr_buf[2];1090 u8 data_buf[4] = { 0 };1091 int ret;1092 1093 if (len > 4)1094 return -EINVAL;1095 1096 put_unaligned_be16(reg, addr_buf);1097 /* Write register address */1098 msgs[0].addr = client->addr;1099 msgs[0].flags = 0;1100 msgs[0].len = ARRAY_SIZE(addr_buf);1101 msgs[0].buf = addr_buf;1102 1103 /* Read data from register */1104 msgs[1].addr = client->addr;1105 msgs[1].flags = I2C_M_RD;1106 msgs[1].len = len;1107 msgs[1].buf = &data_buf[4 - len];1108 1109 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));1110 if (ret != ARRAY_SIZE(msgs))1111 return -EIO;1112 1113 *val = get_unaligned_be32(data_buf);1114 1115 return 0;1116}1117 1118/* Write registers up to 4 at a time */1119static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val)1120{1121 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1122 u8 buf[6];1123 1124 if (len > 4)1125 return -EINVAL;1126 1127 put_unaligned_be16(reg, buf);1128 put_unaligned_be32(val << (8 * (4 - len)), buf + 2);1129 if (i2c_master_send(client, buf, len + 2) != len + 2)1130 return -EIO;1131 1132 return 0;1133}1134 1135/* Write a list of registers */1136static int imx355_write_regs(struct imx355 *imx355,1137 const struct imx355_reg *regs, u32 len)1138{1139 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1140 int ret;1141 u32 i;1142 1143 for (i = 0; i < len; i++) {1144 ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val);1145 if (ret) {1146 dev_err_ratelimited(&client->dev,1147 "write reg 0x%4.4x return err %d",1148 regs[i].address, ret);1149 1150 return ret;1151 }1152 }1153 1154 return 0;1155}1156 1157/* Open sub-device */1158static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1159{1160 struct imx355 *imx355 = to_imx355(sd);1161 struct v4l2_mbus_framefmt *try_fmt =1162 v4l2_subdev_state_get_format(fh->state, 0);1163 1164 mutex_lock(&imx355->mutex);1165 1166 /* Initialize try_fmt */1167 try_fmt->width = imx355->cur_mode->width;1168 try_fmt->height = imx355->cur_mode->height;1169 try_fmt->code = imx355_get_format_code(imx355);1170 try_fmt->field = V4L2_FIELD_NONE;1171 1172 mutex_unlock(&imx355->mutex);1173 1174 return 0;1175}1176 1177static int imx355_set_ctrl(struct v4l2_ctrl *ctrl)1178{1179 struct imx355 *imx355 = container_of(ctrl->handler,1180 struct imx355, ctrl_handler);1181 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1182 s64 max;1183 int ret;1184 1185 /* Propagate change of current control to all related controls */1186 switch (ctrl->id) {1187 case V4L2_CID_VBLANK:1188 /* Update max exposure while meeting expected vblanking */1189 max = imx355->cur_mode->height + ctrl->val - 10;1190 __v4l2_ctrl_modify_range(imx355->exposure,1191 imx355->exposure->minimum,1192 max, imx355->exposure->step, max);1193 break;1194 }1195 1196 /*1197 * Applying V4L2 control value only happens1198 * when power is up for streaming1199 */1200 if (!pm_runtime_get_if_in_use(&client->dev))1201 return 0;1202 1203 switch (ctrl->id) {1204 case V4L2_CID_ANALOGUE_GAIN:1205 /* Analog gain = 1024/(1024 - ctrl->val) times */1206 ret = imx355_write_reg(imx355, IMX355_REG_ANALOG_GAIN, 2,1207 ctrl->val);1208 break;1209 case V4L2_CID_DIGITAL_GAIN:1210 ret = imx355_write_reg(imx355, IMX355_REG_DIG_GAIN_GLOBAL, 2,1211 ctrl->val);1212 break;1213 case V4L2_CID_EXPOSURE:1214 ret = imx355_write_reg(imx355, IMX355_REG_EXPOSURE, 2,1215 ctrl->val);1216 break;1217 case V4L2_CID_VBLANK:1218 /* Update FLL that meets expected vertical blanking */1219 ret = imx355_write_reg(imx355, IMX355_REG_FLL, 2,1220 imx355->cur_mode->height + ctrl->val);1221 break;1222 case V4L2_CID_TEST_PATTERN:1223 ret = imx355_write_reg(imx355, IMX355_REG_TEST_PATTERN,1224 2, ctrl->val);1225 break;1226 case V4L2_CID_HFLIP:1227 case V4L2_CID_VFLIP:1228 ret = imx355_write_reg(imx355, IMX355_REG_ORIENTATION, 1,1229 imx355->hflip->val |1230 imx355->vflip->val << 1);1231 break;1232 default:1233 ret = -EINVAL;1234 dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",1235 ctrl->id, ctrl->val);1236 break;1237 }1238 1239 pm_runtime_put(&client->dev);1240 1241 return ret;1242}1243 1244static const struct v4l2_ctrl_ops imx355_ctrl_ops = {1245 .s_ctrl = imx355_set_ctrl,1246};1247 1248static int imx355_enum_mbus_code(struct v4l2_subdev *sd,1249 struct v4l2_subdev_state *sd_state,1250 struct v4l2_subdev_mbus_code_enum *code)1251{1252 struct imx355 *imx355 = to_imx355(sd);1253 1254 if (code->index > 0)1255 return -EINVAL;1256 1257 mutex_lock(&imx355->mutex);1258 code->code = imx355_get_format_code(imx355);1259 mutex_unlock(&imx355->mutex);1260 1261 return 0;1262}1263 1264static int imx355_enum_frame_size(struct v4l2_subdev *sd,1265 struct v4l2_subdev_state *sd_state,1266 struct v4l2_subdev_frame_size_enum *fse)1267{1268 struct imx355 *imx355 = to_imx355(sd);1269 1270 if (fse->index >= ARRAY_SIZE(supported_modes))1271 return -EINVAL;1272 1273 mutex_lock(&imx355->mutex);1274 if (fse->code != imx355_get_format_code(imx355)) {1275 mutex_unlock(&imx355->mutex);1276 return -EINVAL;1277 }1278 mutex_unlock(&imx355->mutex);1279 1280 fse->min_width = supported_modes[fse->index].width;1281 fse->max_width = fse->min_width;1282 fse->min_height = supported_modes[fse->index].height;1283 fse->max_height = fse->min_height;1284 1285 return 0;1286}1287 1288static void imx355_update_pad_format(struct imx355 *imx355,1289 const struct imx355_mode *mode,1290 struct v4l2_subdev_format *fmt)1291{1292 fmt->format.width = mode->width;1293 fmt->format.height = mode->height;1294 fmt->format.code = imx355_get_format_code(imx355);1295 fmt->format.field = V4L2_FIELD_NONE;1296}1297 1298static int imx355_do_get_pad_format(struct imx355 *imx355,1299 struct v4l2_subdev_state *sd_state,1300 struct v4l2_subdev_format *fmt)1301{1302 struct v4l2_mbus_framefmt *framefmt;1303 1304 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1305 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);1306 fmt->format = *framefmt;1307 } else {1308 imx355_update_pad_format(imx355, imx355->cur_mode, fmt);1309 }1310 1311 return 0;1312}1313 1314static int imx355_get_pad_format(struct v4l2_subdev *sd,1315 struct v4l2_subdev_state *sd_state,1316 struct v4l2_subdev_format *fmt)1317{1318 struct imx355 *imx355 = to_imx355(sd);1319 int ret;1320 1321 mutex_lock(&imx355->mutex);1322 ret = imx355_do_get_pad_format(imx355, sd_state, fmt);1323 mutex_unlock(&imx355->mutex);1324 1325 return ret;1326}1327 1328static int1329imx355_set_pad_format(struct v4l2_subdev *sd,1330 struct v4l2_subdev_state *sd_state,1331 struct v4l2_subdev_format *fmt)1332{1333 struct imx355 *imx355 = to_imx355(sd);1334 const struct imx355_mode *mode;1335 struct v4l2_mbus_framefmt *framefmt;1336 s32 vblank_def;1337 s32 vblank_min;1338 s64 h_blank;1339 u64 pixel_rate;1340 u32 height;1341 1342 mutex_lock(&imx355->mutex);1343 1344 /*1345 * Only one bayer order is supported.1346 * It depends on the flip settings.1347 */1348 fmt->format.code = imx355_get_format_code(imx355);1349 1350 mode = v4l2_find_nearest_size(supported_modes,1351 ARRAY_SIZE(supported_modes),1352 width, height,1353 fmt->format.width, fmt->format.height);1354 imx355_update_pad_format(imx355, mode, fmt);1355 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1356 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);1357 *framefmt = fmt->format;1358 } else {1359 imx355->cur_mode = mode;1360 pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4;1361 do_div(pixel_rate, 10);1362 __v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate);1363 /* Update limits and set FPS to default */1364 height = imx355->cur_mode->height;1365 vblank_def = imx355->cur_mode->fll_def - height;1366 vblank_min = imx355->cur_mode->fll_min - height;1367 height = IMX355_FLL_MAX - height;1368 __v4l2_ctrl_modify_range(imx355->vblank, vblank_min, height, 1,1369 vblank_def);1370 __v4l2_ctrl_s_ctrl(imx355->vblank, vblank_def);1371 h_blank = mode->llp - imx355->cur_mode->width;1372 /*1373 * Currently hblank is not changeable.1374 * So FPS control is done only by vblank.1375 */1376 __v4l2_ctrl_modify_range(imx355->hblank, h_blank,1377 h_blank, 1, h_blank);1378 }1379 1380 mutex_unlock(&imx355->mutex);1381 1382 return 0;1383}1384 1385/* Start streaming */1386static int imx355_start_streaming(struct imx355 *imx355)1387{1388 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1389 const struct imx355_reg_list *reg_list;1390 int ret;1391 1392 /* Global Setting */1393 reg_list = &imx355_global_setting;1394 ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);1395 if (ret) {1396 dev_err(&client->dev, "failed to set global settings");1397 return ret;1398 }1399 1400 /* Apply default values of current mode */1401 reg_list = &imx355->cur_mode->reg_list;1402 ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);1403 if (ret) {1404 dev_err(&client->dev, "failed to set mode");1405 return ret;1406 }1407 1408 /* set digital gain control to all color mode */1409 ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);1410 if (ret)1411 return ret;1412 1413 /* Apply customized values from user */1414 ret = __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler);1415 if (ret)1416 return ret;1417 1418 return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,1419 1, IMX355_MODE_STREAMING);1420}1421 1422/* Stop streaming */1423static int imx355_stop_streaming(struct imx355 *imx355)1424{1425 return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,1426 1, IMX355_MODE_STANDBY);1427}1428 1429static int imx355_set_stream(struct v4l2_subdev *sd, int enable)1430{1431 struct imx355 *imx355 = to_imx355(sd);1432 struct i2c_client *client = v4l2_get_subdevdata(sd);1433 int ret = 0;1434 1435 mutex_lock(&imx355->mutex);1436 1437 if (enable) {1438 ret = pm_runtime_resume_and_get(&client->dev);1439 if (ret < 0)1440 goto err_unlock;1441 1442 /*1443 * Apply default & customized values1444 * and then start streaming.1445 */1446 ret = imx355_start_streaming(imx355);1447 if (ret)1448 goto err_rpm_put;1449 } else {1450 imx355_stop_streaming(imx355);1451 pm_runtime_put(&client->dev);1452 }1453 1454 /* vflip and hflip cannot change during streaming */1455 __v4l2_ctrl_grab(imx355->vflip, enable);1456 __v4l2_ctrl_grab(imx355->hflip, enable);1457 1458 mutex_unlock(&imx355->mutex);1459 1460 return ret;1461 1462err_rpm_put:1463 pm_runtime_put(&client->dev);1464err_unlock:1465 mutex_unlock(&imx355->mutex);1466 1467 return ret;1468}1469 1470/* Verify chip ID */1471static int imx355_identify_module(struct imx355 *imx355)1472{1473 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1474 int ret;1475 u32 val;1476 1477 ret = imx355_read_reg(imx355, IMX355_REG_CHIP_ID, 2, &val);1478 if (ret)1479 return ret;1480 1481 if (val != IMX355_CHIP_ID) {1482 dev_err(&client->dev, "chip id mismatch: %x!=%x",1483 IMX355_CHIP_ID, val);1484 return -EIO;1485 }1486 return 0;1487}1488 1489static const struct v4l2_subdev_core_ops imx355_subdev_core_ops = {1490 .subscribe_event = v4l2_ctrl_subdev_subscribe_event,1491 .unsubscribe_event = v4l2_event_subdev_unsubscribe,1492};1493 1494static const struct v4l2_subdev_video_ops imx355_video_ops = {1495 .s_stream = imx355_set_stream,1496};1497 1498static const struct v4l2_subdev_pad_ops imx355_pad_ops = {1499 .enum_mbus_code = imx355_enum_mbus_code,1500 .get_fmt = imx355_get_pad_format,1501 .set_fmt = imx355_set_pad_format,1502 .enum_frame_size = imx355_enum_frame_size,1503};1504 1505static const struct v4l2_subdev_ops imx355_subdev_ops = {1506 .core = &imx355_subdev_core_ops,1507 .video = &imx355_video_ops,1508 .pad = &imx355_pad_ops,1509};1510 1511static const struct media_entity_operations imx355_subdev_entity_ops = {1512 .link_validate = v4l2_subdev_link_validate,1513};1514 1515static const struct v4l2_subdev_internal_ops imx355_internal_ops = {1516 .open = imx355_open,1517};1518 1519/* Initialize control handlers */1520static int imx355_init_controls(struct imx355 *imx355)1521{1522 struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);1523 struct v4l2_fwnode_device_properties props;1524 struct v4l2_ctrl_handler *ctrl_hdlr;1525 s64 exposure_max;1526 s64 vblank_def;1527 s64 vblank_min;1528 s64 hblank;1529 u64 pixel_rate;1530 const struct imx355_mode *mode;1531 u32 max;1532 int ret;1533 1534 ctrl_hdlr = &imx355->ctrl_handler;1535 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);1536 if (ret)1537 return ret;1538 1539 ctrl_hdlr->lock = &imx355->mutex;1540 max = ARRAY_SIZE(link_freq_menu_items) - 1;1541 imx355->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx355_ctrl_ops,1542 V4L2_CID_LINK_FREQ, max, 0,1543 link_freq_menu_items);1544 if (imx355->link_freq)1545 imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;1546 1547 /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */1548 pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4;1549 do_div(pixel_rate, 10);1550 /* By default, PIXEL_RATE is read only */1551 imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1552 V4L2_CID_PIXEL_RATE, pixel_rate,1553 pixel_rate, 1, pixel_rate);1554 1555 /* Initialize vblank/hblank/exposure parameters based on current mode */1556 mode = imx355->cur_mode;1557 vblank_def = mode->fll_def - mode->height;1558 vblank_min = mode->fll_min - mode->height;1559 imx355->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1560 V4L2_CID_VBLANK, vblank_min,1561 IMX355_FLL_MAX - mode->height,1562 1, vblank_def);1563 1564 hblank = mode->llp - mode->width;1565 imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1566 V4L2_CID_HBLANK, hblank, hblank,1567 1, hblank);1568 if (imx355->hblank)1569 imx355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;1570 1571 /* fll >= exposure time + adjust parameter (default value is 10) */1572 exposure_max = mode->fll_def - 10;1573 imx355->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1574 V4L2_CID_EXPOSURE,1575 IMX355_EXPOSURE_MIN, exposure_max,1576 IMX355_EXPOSURE_STEP,1577 IMX355_EXPOSURE_DEFAULT);1578 1579 imx355->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1580 V4L2_CID_HFLIP, 0, 1, 1, 0);1581 if (imx355->hflip)1582 imx355->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;1583 imx355->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,1584 V4L2_CID_VFLIP, 0, 1, 1, 0);1585 if (imx355->vflip)1586 imx355->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;1587 1588 v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,1589 IMX355_ANA_GAIN_MIN, IMX355_ANA_GAIN_MAX,1590 IMX355_ANA_GAIN_STEP, IMX355_ANA_GAIN_DEFAULT);1591 1592 /* Digital gain */1593 v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_DIGITAL_GAIN,1594 IMX355_DGTL_GAIN_MIN, IMX355_DGTL_GAIN_MAX,1595 IMX355_DGTL_GAIN_STEP, IMX355_DGTL_GAIN_DEFAULT);1596 1597 v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx355_ctrl_ops,1598 V4L2_CID_TEST_PATTERN,1599 ARRAY_SIZE(imx355_test_pattern_menu) - 1,1600 0, 0, imx355_test_pattern_menu);1601 if (ctrl_hdlr->error) {1602 ret = ctrl_hdlr->error;1603 dev_err(&client->dev, "control init failed: %d", ret);1604 goto error;1605 }1606 1607 ret = v4l2_fwnode_device_parse(&client->dev, &props);1608 if (ret)1609 goto error;1610 1611 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx355_ctrl_ops,1612 &props);1613 if (ret)1614 goto error;1615 1616 imx355->sd.ctrl_handler = ctrl_hdlr;1617 1618 return 0;1619 1620error:1621 v4l2_ctrl_handler_free(ctrl_hdlr);1622 1623 return ret;1624}1625 1626static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev)1627{1628 struct imx355_hwcfg *cfg;1629 struct v4l2_fwnode_endpoint bus_cfg = {1630 .bus_type = V4L2_MBUS_CSI2_DPHY1631 };1632 struct fwnode_handle *ep;1633 struct fwnode_handle *fwnode = dev_fwnode(dev);1634 int ret;1635 1636 if (!fwnode)1637 return NULL;1638 1639 ep = fwnode_graph_get_next_endpoint(fwnode, NULL);1640 if (!ep)1641 return NULL;1642 1643 ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);1644 if (ret)1645 goto out_err;1646 1647 cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);1648 if (!cfg)1649 goto out_err;1650 1651 ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",1652 &cfg->ext_clk);1653 if (ret) {1654 dev_err(dev, "can't get clock frequency");1655 goto out_err;1656 }1657 1658 dev_dbg(dev, "ext clk: %d", cfg->ext_clk);1659 if (cfg->ext_clk != IMX355_EXT_CLK) {1660 dev_err(dev, "external clock %d is not supported",1661 cfg->ext_clk);1662 goto out_err;1663 }1664 1665 ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,1666 bus_cfg.nr_of_link_frequencies,1667 link_freq_menu_items,1668 ARRAY_SIZE(link_freq_menu_items),1669 &cfg->link_freq_bitmap);1670 if (ret)1671 goto out_err;1672 1673 v4l2_fwnode_endpoint_free(&bus_cfg);1674 fwnode_handle_put(ep);1675 return cfg;1676 1677out_err:1678 v4l2_fwnode_endpoint_free(&bus_cfg);1679 fwnode_handle_put(ep);1680 return NULL;1681}1682 1683static int imx355_probe(struct i2c_client *client)1684{1685 struct imx355 *imx355;1686 int ret;1687 1688 imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL);1689 if (!imx355)1690 return -ENOMEM;1691 1692 mutex_init(&imx355->mutex);1693 1694 /* Initialize subdev */1695 v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops);1696 1697 /* Check module identity */1698 ret = imx355_identify_module(imx355);1699 if (ret) {1700 dev_err(&client->dev, "failed to find sensor: %d", ret);1701 goto error_probe;1702 }1703 1704 imx355->hwcfg = imx355_get_hwcfg(&client->dev);1705 if (!imx355->hwcfg) {1706 dev_err(&client->dev, "failed to get hwcfg");1707 ret = -ENODEV;1708 goto error_probe;1709 }1710 1711 /* Set default mode to max resolution */1712 imx355->cur_mode = &supported_modes[0];1713 1714 ret = imx355_init_controls(imx355);1715 if (ret) {1716 dev_err(&client->dev, "failed to init controls: %d", ret);1717 goto error_probe;1718 }1719 1720 /* Initialize subdev */1721 imx355->sd.internal_ops = &imx355_internal_ops;1722 imx355->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |1723 V4L2_SUBDEV_FL_HAS_EVENTS;1724 imx355->sd.entity.ops = &imx355_subdev_entity_ops;1725 imx355->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1726 1727 /* Initialize source pad */1728 imx355->pad.flags = MEDIA_PAD_FL_SOURCE;1729 ret = media_entity_pads_init(&imx355->sd.entity, 1, &imx355->pad);1730 if (ret) {1731 dev_err(&client->dev, "failed to init entity pads: %d", ret);1732 goto error_handler_free;1733 }1734 1735 /*1736 * Device is already turned on by i2c-core with ACPI domain PM.1737 * Enable runtime PM and turn off the device.1738 */1739 pm_runtime_set_active(&client->dev);1740 pm_runtime_enable(&client->dev);1741 pm_runtime_idle(&client->dev);1742 1743 ret = v4l2_async_register_subdev_sensor(&imx355->sd);1744 if (ret < 0)1745 goto error_media_entity_runtime_pm;1746 1747 return 0;1748 1749error_media_entity_runtime_pm:1750 pm_runtime_disable(&client->dev);1751 pm_runtime_set_suspended(&client->dev);1752 media_entity_cleanup(&imx355->sd.entity);1753 1754error_handler_free:1755 v4l2_ctrl_handler_free(imx355->sd.ctrl_handler);1756 1757error_probe:1758 mutex_destroy(&imx355->mutex);1759 1760 return ret;1761}1762 1763static void imx355_remove(struct i2c_client *client)1764{1765 struct v4l2_subdev *sd = i2c_get_clientdata(client);1766 struct imx355 *imx355 = to_imx355(sd);1767 1768 v4l2_async_unregister_subdev(sd);1769 media_entity_cleanup(&sd->entity);1770 v4l2_ctrl_handler_free(sd->ctrl_handler);1771 1772 pm_runtime_disable(&client->dev);1773 pm_runtime_set_suspended(&client->dev);1774 1775 mutex_destroy(&imx355->mutex);1776}1777 1778static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = {1779 { "SONY355A" },1780 { /* sentinel */ }1781};1782MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids);1783 1784static struct i2c_driver imx355_i2c_driver = {1785 .driver = {1786 .name = "imx355",1787 .acpi_match_table = ACPI_PTR(imx355_acpi_ids),1788 },1789 .probe = imx355_probe,1790 .remove = imx355_remove,1791};1792module_i2c_driver(imx355_i2c_driver);1793 1794MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");1795MODULE_AUTHOR("Rapolu, Chiranjeevi");1796MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");1797MODULE_AUTHOR("Yang, Hyungwoo");1798MODULE_DESCRIPTION("Sony imx355 sensor driver");1799MODULE_LICENSE("GPL v2");1800