cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx355.c (41464B)


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