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

imx319.c (55336B)


      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 IMX319_REG_MODE_SELECT		0x0100
     15#define IMX319_MODE_STANDBY		0x00
     16#define IMX319_MODE_STREAMING		0x01
     17
     18/* Chip ID */
     19#define IMX319_REG_CHIP_ID		0x0016
     20#define IMX319_CHIP_ID			0x0319
     21
     22/* V_TIMING internal */
     23#define IMX319_REG_FLL			0x0340
     24#define IMX319_FLL_MAX			0xffff
     25
     26/* Exposure control */
     27#define IMX319_REG_EXPOSURE		0x0202
     28#define IMX319_EXPOSURE_MIN		1
     29#define IMX319_EXPOSURE_STEP		1
     30#define IMX319_EXPOSURE_DEFAULT		0x04f6
     31
     32/*
     33 *  the digital control register for all color control looks like:
     34 *  +-----------------+------------------+
     35 *  |      [7:0]      |       [15:8]     |
     36 *  +-----------------+------------------+
     37 *  |	  0x020f      |       0x020e     |
     38 *  --------------------------------------
     39 *  it is used to calculate the digital gain times value(integral + fractional)
     40 *  the [15:8] bits is the fractional part and [7:0] bits is the integral
     41 *  calculation equation is:
     42 *      gain value (unit: times) = REG[15:8] + REG[7:0]/0x100
     43 *  Only value in 0x0100 ~ 0x0FFF range is allowed.
     44 *  Analog gain use 10 bits in the registers and allowed range is 0 ~ 960
     45 */
     46/* Analog gain control */
     47#define IMX319_REG_ANALOG_GAIN		0x0204
     48#define IMX319_ANA_GAIN_MIN		0
     49#define IMX319_ANA_GAIN_MAX		960
     50#define IMX319_ANA_GAIN_STEP		1
     51#define IMX319_ANA_GAIN_DEFAULT		0
     52
     53/* Digital gain control */
     54#define IMX319_REG_DPGA_USE_GLOBAL_GAIN	0x3ff9
     55#define IMX319_REG_DIG_GAIN_GLOBAL	0x020e
     56#define IMX319_DGTL_GAIN_MIN		256
     57#define IMX319_DGTL_GAIN_MAX		4095
     58#define IMX319_DGTL_GAIN_STEP		1
     59#define IMX319_DGTL_GAIN_DEFAULT	256
     60
     61/* Test Pattern Control */
     62#define IMX319_REG_TEST_PATTERN		0x0600
     63#define IMX319_TEST_PATTERN_DISABLED		0
     64#define IMX319_TEST_PATTERN_SOLID_COLOR		1
     65#define IMX319_TEST_PATTERN_COLOR_BARS		2
     66#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS	3
     67#define IMX319_TEST_PATTERN_PN9			4
     68
     69/* Flip Control */
     70#define IMX319_REG_ORIENTATION		0x0101
     71
     72/* default link frequency and external clock */
     73#define IMX319_LINK_FREQ_DEFAULT	482400000
     74#define IMX319_EXT_CLK			19200000
     75#define IMX319_LINK_FREQ_INDEX		0
     76
     77struct imx319_reg {
     78	u16 address;
     79	u8 val;
     80};
     81
     82struct imx319_reg_list {
     83	u32 num_of_regs;
     84	const struct imx319_reg *regs;
     85};
     86
     87/* Mode : resolution and related config&values */
     88struct imx319_mode {
     89	/* Frame width */
     90	u32 width;
     91	/* Frame height */
     92	u32 height;
     93
     94	/* V-timing */
     95	u32 fll_def;
     96	u32 fll_min;
     97
     98	/* H-timing */
     99	u32 llp;
    100
    101	/* index of link frequency */
    102	u32 link_freq_index;
    103
    104	/* Default register values */
    105	struct imx319_reg_list reg_list;
    106};
    107
    108struct imx319_hwcfg {
    109	u32 ext_clk;			/* sensor external clk */
    110	s64 *link_freqs;		/* CSI-2 link frequencies */
    111	unsigned int nr_of_link_freqs;
    112};
    113
    114struct imx319 {
    115	struct v4l2_subdev sd;
    116	struct media_pad pad;
    117
    118	struct v4l2_ctrl_handler ctrl_handler;
    119	/* V4L2 Controls */
    120	struct v4l2_ctrl *link_freq;
    121	struct v4l2_ctrl *pixel_rate;
    122	struct v4l2_ctrl *vblank;
    123	struct v4l2_ctrl *hblank;
    124	struct v4l2_ctrl *exposure;
    125	struct v4l2_ctrl *vflip;
    126	struct v4l2_ctrl *hflip;
    127
    128	/* Current mode */
    129	const struct imx319_mode *cur_mode;
    130
    131	struct imx319_hwcfg *hwcfg;
    132	s64 link_def_freq;	/* CSI-2 link default frequency */
    133
    134	/*
    135	 * Mutex for serialized access:
    136	 * Protect sensor set pad format and start/stop streaming safely.
    137	 * Protect access to sensor v4l2 controls.
    138	 */
    139	struct mutex mutex;
    140
    141	/* Streaming on/off */
    142	bool streaming;
    143	/* True if the device has been identified */
    144	bool identified;
    145};
    146
    147static const struct imx319_reg imx319_global_regs[] = {
    148	{ 0x0136, 0x13 },
    149	{ 0x0137, 0x33 },
    150	{ 0x3c7e, 0x05 },
    151	{ 0x3c7f, 0x07 },
    152	{ 0x4d39, 0x0b },
    153	{ 0x4d41, 0x33 },
    154	{ 0x4d43, 0x0c },
    155	{ 0x4d49, 0x89 },
    156	{ 0x4e05, 0x0b },
    157	{ 0x4e0d, 0x33 },
    158	{ 0x4e0f, 0x0c },
    159	{ 0x4e15, 0x89 },
    160	{ 0x4e49, 0x2a },
    161	{ 0x4e51, 0x33 },
    162	{ 0x4e53, 0x0c },
    163	{ 0x4e59, 0x89 },
    164	{ 0x5601, 0x4f },
    165	{ 0x560b, 0x45 },
    166	{ 0x562f, 0x0a },
    167	{ 0x5643, 0x0a },
    168	{ 0x5645, 0x0c },
    169	{ 0x56ef, 0x51 },
    170	{ 0x586f, 0x33 },
    171	{ 0x5873, 0x89 },
    172	{ 0x5905, 0x33 },
    173	{ 0x5907, 0x89 },
    174	{ 0x590d, 0x33 },
    175	{ 0x590f, 0x89 },
    176	{ 0x5915, 0x33 },
    177	{ 0x5917, 0x89 },
    178	{ 0x5969, 0x1c },
    179	{ 0x596b, 0x72 },
    180	{ 0x5971, 0x33 },
    181	{ 0x5973, 0x89 },
    182	{ 0x5975, 0x33 },
    183	{ 0x5977, 0x89 },
    184	{ 0x5979, 0x1c },
    185	{ 0x597b, 0x72 },
    186	{ 0x5985, 0x33 },
    187	{ 0x5987, 0x89 },
    188	{ 0x5999, 0x1c },
    189	{ 0x599b, 0x72 },
    190	{ 0x59a5, 0x33 },
    191	{ 0x59a7, 0x89 },
    192	{ 0x7485, 0x08 },
    193	{ 0x7487, 0x0c },
    194	{ 0x7489, 0xc7 },
    195	{ 0x748b, 0x8b },
    196	{ 0x9004, 0x09 },
    197	{ 0x9200, 0x6a },
    198	{ 0x9201, 0x22 },
    199	{ 0x9202, 0x6a },
    200	{ 0x9203, 0x23 },
    201	{ 0x9204, 0x5f },
    202	{ 0x9205, 0x23 },
    203	{ 0x9206, 0x5f },
    204	{ 0x9207, 0x24 },
    205	{ 0x9208, 0x5f },
    206	{ 0x9209, 0x26 },
    207	{ 0x920a, 0x5f },
    208	{ 0x920b, 0x27 },
    209	{ 0x920c, 0x5f },
    210	{ 0x920d, 0x29 },
    211	{ 0x920e, 0x5f },
    212	{ 0x920f, 0x2a },
    213	{ 0x9210, 0x5f },
    214	{ 0x9211, 0x2c },
    215	{ 0xbc22, 0x1a },
    216	{ 0xf01f, 0x04 },
    217	{ 0xf021, 0x03 },
    218	{ 0xf023, 0x02 },
    219	{ 0xf03d, 0x05 },
    220	{ 0xf03f, 0x03 },
    221	{ 0xf041, 0x02 },
    222	{ 0xf0af, 0x04 },
    223	{ 0xf0b1, 0x03 },
    224	{ 0xf0b3, 0x02 },
    225	{ 0xf0cd, 0x05 },
    226	{ 0xf0cf, 0x03 },
    227	{ 0xf0d1, 0x02 },
    228	{ 0xf13f, 0x04 },
    229	{ 0xf141, 0x03 },
    230	{ 0xf143, 0x02 },
    231	{ 0xf15d, 0x05 },
    232	{ 0xf15f, 0x03 },
    233	{ 0xf161, 0x02 },
    234	{ 0xf1cf, 0x04 },
    235	{ 0xf1d1, 0x03 },
    236	{ 0xf1d3, 0x02 },
    237	{ 0xf1ed, 0x05 },
    238	{ 0xf1ef, 0x03 },
    239	{ 0xf1f1, 0x02 },
    240	{ 0xf287, 0x04 },
    241	{ 0xf289, 0x03 },
    242	{ 0xf28b, 0x02 },
    243	{ 0xf2a5, 0x05 },
    244	{ 0xf2a7, 0x03 },
    245	{ 0xf2a9, 0x02 },
    246	{ 0xf2b7, 0x04 },
    247	{ 0xf2b9, 0x03 },
    248	{ 0xf2bb, 0x02 },
    249	{ 0xf2d5, 0x05 },
    250	{ 0xf2d7, 0x03 },
    251	{ 0xf2d9, 0x02 },
    252};
    253
    254static const struct imx319_reg_list imx319_global_setting = {
    255	.num_of_regs = ARRAY_SIZE(imx319_global_regs),
    256	.regs = imx319_global_regs,
    257};
    258
    259static const struct imx319_reg mode_3264x2448_regs[] = {
    260	{ 0x0112, 0x0a },
    261	{ 0x0113, 0x0a },
    262	{ 0x0114, 0x03 },
    263	{ 0x0342, 0x0f },
    264	{ 0x0343, 0x80 },
    265	{ 0x0340, 0x0c },
    266	{ 0x0341, 0xaa },
    267	{ 0x0344, 0x00 },
    268	{ 0x0345, 0x00 },
    269	{ 0x0346, 0x00 },
    270	{ 0x0347, 0x00 },
    271	{ 0x0348, 0x0c },
    272	{ 0x0349, 0xcf },
    273	{ 0x034a, 0x09 },
    274	{ 0x034b, 0x9f },
    275	{ 0x0220, 0x00 },
    276	{ 0x0221, 0x11 },
    277	{ 0x0381, 0x01 },
    278	{ 0x0383, 0x01 },
    279	{ 0x0385, 0x01 },
    280	{ 0x0387, 0x01 },
    281	{ 0x0900, 0x00 },
    282	{ 0x0901, 0x11 },
    283	{ 0x0902, 0x0a },
    284	{ 0x3140, 0x02 },
    285	{ 0x3141, 0x00 },
    286	{ 0x3f0d, 0x0a },
    287	{ 0x3f14, 0x01 },
    288	{ 0x3f3c, 0x01 },
    289	{ 0x3f4d, 0x01 },
    290	{ 0x3f4c, 0x01 },
    291	{ 0x4254, 0x7f },
    292	{ 0x0401, 0x00 },
    293	{ 0x0404, 0x00 },
    294	{ 0x0405, 0x10 },
    295	{ 0x0408, 0x00 },
    296	{ 0x0409, 0x08 },
    297	{ 0x040a, 0x00 },
    298	{ 0x040b, 0x08 },
    299	{ 0x040c, 0x0c },
    300	{ 0x040d, 0xc0 },
    301	{ 0x040e, 0x09 },
    302	{ 0x040f, 0x90 },
    303	{ 0x034c, 0x0c },
    304	{ 0x034d, 0xc0 },
    305	{ 0x034e, 0x09 },
    306	{ 0x034f, 0x90 },
    307	{ 0x3261, 0x00 },
    308	{ 0x3264, 0x00 },
    309	{ 0x3265, 0x10 },
    310	{ 0x0301, 0x05 },
    311	{ 0x0303, 0x04 },
    312	{ 0x0305, 0x04 },
    313	{ 0x0306, 0x01 },
    314	{ 0x0307, 0x92 },
    315	{ 0x0309, 0x0a },
    316	{ 0x030b, 0x02 },
    317	{ 0x030d, 0x02 },
    318	{ 0x030e, 0x00 },
    319	{ 0x030f, 0xfa },
    320	{ 0x0310, 0x00 },
    321	{ 0x0820, 0x0f },
    322	{ 0x0821, 0x13 },
    323	{ 0x0822, 0x33 },
    324	{ 0x0823, 0x33 },
    325	{ 0x3e20, 0x01 },
    326	{ 0x3e37, 0x00 },
    327	{ 0x3e3b, 0x01 },
    328	{ 0x38a3, 0x01 },
    329	{ 0x38a8, 0x00 },
    330	{ 0x38a9, 0x00 },
    331	{ 0x38aa, 0x00 },
    332	{ 0x38ab, 0x00 },
    333	{ 0x3234, 0x00 },
    334	{ 0x3fc1, 0x00 },
    335	{ 0x3235, 0x00 },
    336	{ 0x3802, 0x00 },
    337	{ 0x3143, 0x04 },
    338	{ 0x360a, 0x00 },
    339	{ 0x0b00, 0x00 },
    340	{ 0x0106, 0x00 },
    341	{ 0x0b05, 0x01 },
    342	{ 0x0b06, 0x01 },
    343	{ 0x3230, 0x00 },
    344	{ 0x3602, 0x01 },
    345	{ 0x3607, 0x01 },
    346	{ 0x3c00, 0x00 },
    347	{ 0x3c01, 0x48 },
    348	{ 0x3c02, 0xc8 },
    349	{ 0x3c03, 0xaa },
    350	{ 0x3c04, 0x91 },
    351	{ 0x3c05, 0x54 },
    352	{ 0x3c06, 0x26 },
    353	{ 0x3c07, 0x20 },
    354	{ 0x3c08, 0x51 },
    355	{ 0x3d80, 0x00 },
    356	{ 0x3f50, 0x00 },
    357	{ 0x3f56, 0x00 },
    358	{ 0x3f57, 0x30 },
    359	{ 0x3f78, 0x01 },
    360	{ 0x3f79, 0x18 },
    361	{ 0x3f7c, 0x00 },
    362	{ 0x3f7d, 0x00 },
    363	{ 0x3fba, 0x00 },
    364	{ 0x3fbb, 0x00 },
    365	{ 0xa081, 0x00 },
    366	{ 0xe014, 0x00 },
    367	{ 0x0202, 0x0a },
    368	{ 0x0203, 0x7a },
    369	{ 0x0224, 0x01 },
    370	{ 0x0225, 0xf4 },
    371	{ 0x0204, 0x00 },
    372	{ 0x0205, 0x00 },
    373	{ 0x0216, 0x00 },
    374	{ 0x0217, 0x00 },
    375	{ 0x020e, 0x01 },
    376	{ 0x020f, 0x00 },
    377	{ 0x0210, 0x01 },
    378	{ 0x0211, 0x00 },
    379	{ 0x0212, 0x01 },
    380	{ 0x0213, 0x00 },
    381	{ 0x0214, 0x01 },
    382	{ 0x0215, 0x00 },
    383	{ 0x0218, 0x01 },
    384	{ 0x0219, 0x00 },
    385	{ 0x3614, 0x00 },
    386	{ 0x3616, 0x0d },
    387	{ 0x3617, 0x56 },
    388	{ 0xb612, 0x20 },
    389	{ 0xb613, 0x20 },
    390	{ 0xb614, 0x20 },
    391	{ 0xb615, 0x20 },
    392	{ 0xb616, 0x0a },
    393	{ 0xb617, 0x0a },
    394	{ 0xb618, 0x20 },
    395	{ 0xb619, 0x20 },
    396	{ 0xb61a, 0x20 },
    397	{ 0xb61b, 0x20 },
    398	{ 0xb61c, 0x0a },
    399	{ 0xb61d, 0x0a },
    400	{ 0xb666, 0x30 },
    401	{ 0xb667, 0x30 },
    402	{ 0xb668, 0x30 },
    403	{ 0xb669, 0x30 },
    404	{ 0xb66a, 0x14 },
    405	{ 0xb66b, 0x14 },
    406	{ 0xb66c, 0x20 },
    407	{ 0xb66d, 0x20 },
    408	{ 0xb66e, 0x20 },
    409	{ 0xb66f, 0x20 },
    410	{ 0xb670, 0x10 },
    411	{ 0xb671, 0x10 },
    412	{ 0x3237, 0x00 },
    413	{ 0x3900, 0x00 },
    414	{ 0x3901, 0x00 },
    415	{ 0x3902, 0x00 },
    416	{ 0x3904, 0x00 },
    417	{ 0x3905, 0x00 },
    418	{ 0x3906, 0x00 },
    419	{ 0x3907, 0x00 },
    420	{ 0x3908, 0x00 },
    421	{ 0x3909, 0x00 },
    422	{ 0x3912, 0x00 },
    423	{ 0x3930, 0x00 },
    424	{ 0x3931, 0x00 },
    425	{ 0x3933, 0x00 },
    426	{ 0x3934, 0x00 },
    427	{ 0x3935, 0x00 },
    428	{ 0x3936, 0x00 },
    429	{ 0x3937, 0x00 },
    430	{ 0x30ac, 0x00 },
    431};
    432
    433static const struct imx319_reg mode_3280x2464_regs[] = {
    434	{ 0x0112, 0x0a },
    435	{ 0x0113, 0x0a },
    436	{ 0x0114, 0x03 },
    437	{ 0x0342, 0x0f },
    438	{ 0x0343, 0x80 },
    439	{ 0x0340, 0x0c },
    440	{ 0x0341, 0xaa },
    441	{ 0x0344, 0x00 },
    442	{ 0x0345, 0x00 },
    443	{ 0x0346, 0x00 },
    444	{ 0x0347, 0x00 },
    445	{ 0x0348, 0x0c },
    446	{ 0x0349, 0xcf },
    447	{ 0x034a, 0x09 },
    448	{ 0x034b, 0x9f },
    449	{ 0x0220, 0x00 },
    450	{ 0x0221, 0x11 },
    451	{ 0x0381, 0x01 },
    452	{ 0x0383, 0x01 },
    453	{ 0x0385, 0x01 },
    454	{ 0x0387, 0x01 },
    455	{ 0x0900, 0x00 },
    456	{ 0x0901, 0x11 },
    457	{ 0x0902, 0x0a },
    458	{ 0x3140, 0x02 },
    459	{ 0x3141, 0x00 },
    460	{ 0x3f0d, 0x0a },
    461	{ 0x3f14, 0x01 },
    462	{ 0x3f3c, 0x01 },
    463	{ 0x3f4d, 0x01 },
    464	{ 0x3f4c, 0x01 },
    465	{ 0x4254, 0x7f },
    466	{ 0x0401, 0x00 },
    467	{ 0x0404, 0x00 },
    468	{ 0x0405, 0x10 },
    469	{ 0x0408, 0x00 },
    470	{ 0x0409, 0x00 },
    471	{ 0x040a, 0x00 },
    472	{ 0x040b, 0x00 },
    473	{ 0x040c, 0x0c },
    474	{ 0x040d, 0xd0 },
    475	{ 0x040e, 0x09 },
    476	{ 0x040f, 0xa0 },
    477	{ 0x034c, 0x0c },
    478	{ 0x034d, 0xd0 },
    479	{ 0x034e, 0x09 },
    480	{ 0x034f, 0xa0 },
    481	{ 0x3261, 0x00 },
    482	{ 0x3264, 0x00 },
    483	{ 0x3265, 0x10 },
    484	{ 0x0301, 0x05 },
    485	{ 0x0303, 0x04 },
    486	{ 0x0305, 0x04 },
    487	{ 0x0306, 0x01 },
    488	{ 0x0307, 0x92 },
    489	{ 0x0309, 0x0a },
    490	{ 0x030b, 0x02 },
    491	{ 0x030d, 0x02 },
    492	{ 0x030e, 0x00 },
    493	{ 0x030f, 0xfa },
    494	{ 0x0310, 0x00 },
    495	{ 0x0820, 0x0f },
    496	{ 0x0821, 0x13 },
    497	{ 0x0822, 0x33 },
    498	{ 0x0823, 0x33 },
    499	{ 0x3e20, 0x01 },
    500	{ 0x3e37, 0x00 },
    501	{ 0x3e3b, 0x01 },
    502	{ 0x38a3, 0x01 },
    503	{ 0x38a8, 0x00 },
    504	{ 0x38a9, 0x00 },
    505	{ 0x38aa, 0x00 },
    506	{ 0x38ab, 0x00 },
    507	{ 0x3234, 0x00 },
    508	{ 0x3fc1, 0x00 },
    509	{ 0x3235, 0x00 },
    510	{ 0x3802, 0x00 },
    511	{ 0x3143, 0x04 },
    512	{ 0x360a, 0x00 },
    513	{ 0x0b00, 0x00 },
    514	{ 0x0106, 0x00 },
    515	{ 0x0b05, 0x01 },
    516	{ 0x0b06, 0x01 },
    517	{ 0x3230, 0x00 },
    518	{ 0x3602, 0x01 },
    519	{ 0x3607, 0x01 },
    520	{ 0x3c00, 0x00 },
    521	{ 0x3c01, 0x48 },
    522	{ 0x3c02, 0xc8 },
    523	{ 0x3c03, 0xaa },
    524	{ 0x3c04, 0x91 },
    525	{ 0x3c05, 0x54 },
    526	{ 0x3c06, 0x26 },
    527	{ 0x3c07, 0x20 },
    528	{ 0x3c08, 0x51 },
    529	{ 0x3d80, 0x00 },
    530	{ 0x3f50, 0x00 },
    531	{ 0x3f56, 0x00 },
    532	{ 0x3f57, 0x30 },
    533	{ 0x3f78, 0x01 },
    534	{ 0x3f79, 0x18 },
    535	{ 0x3f7c, 0x00 },
    536	{ 0x3f7d, 0x00 },
    537	{ 0x3fba, 0x00 },
    538	{ 0x3fbb, 0x00 },
    539	{ 0xa081, 0x00 },
    540	{ 0xe014, 0x00 },
    541	{ 0x0202, 0x0a },
    542	{ 0x0203, 0x7a },
    543	{ 0x0224, 0x01 },
    544	{ 0x0225, 0xf4 },
    545	{ 0x0204, 0x00 },
    546	{ 0x0205, 0x00 },
    547	{ 0x0216, 0x00 },
    548	{ 0x0217, 0x00 },
    549	{ 0x020e, 0x01 },
    550	{ 0x020f, 0x00 },
    551	{ 0x0210, 0x01 },
    552	{ 0x0211, 0x00 },
    553	{ 0x0212, 0x01 },
    554	{ 0x0213, 0x00 },
    555	{ 0x0214, 0x01 },
    556	{ 0x0215, 0x00 },
    557	{ 0x0218, 0x01 },
    558	{ 0x0219, 0x00 },
    559	{ 0x3614, 0x00 },
    560	{ 0x3616, 0x0d },
    561	{ 0x3617, 0x56 },
    562	{ 0xb612, 0x20 },
    563	{ 0xb613, 0x20 },
    564	{ 0xb614, 0x20 },
    565	{ 0xb615, 0x20 },
    566	{ 0xb616, 0x0a },
    567	{ 0xb617, 0x0a },
    568	{ 0xb618, 0x20 },
    569	{ 0xb619, 0x20 },
    570	{ 0xb61a, 0x20 },
    571	{ 0xb61b, 0x20 },
    572	{ 0xb61c, 0x0a },
    573	{ 0xb61d, 0x0a },
    574	{ 0xb666, 0x30 },
    575	{ 0xb667, 0x30 },
    576	{ 0xb668, 0x30 },
    577	{ 0xb669, 0x30 },
    578	{ 0xb66a, 0x14 },
    579	{ 0xb66b, 0x14 },
    580	{ 0xb66c, 0x20 },
    581	{ 0xb66d, 0x20 },
    582	{ 0xb66e, 0x20 },
    583	{ 0xb66f, 0x20 },
    584	{ 0xb670, 0x10 },
    585	{ 0xb671, 0x10 },
    586	{ 0x3237, 0x00 },
    587	{ 0x3900, 0x00 },
    588	{ 0x3901, 0x00 },
    589	{ 0x3902, 0x00 },
    590	{ 0x3904, 0x00 },
    591	{ 0x3905, 0x00 },
    592	{ 0x3906, 0x00 },
    593	{ 0x3907, 0x00 },
    594	{ 0x3908, 0x00 },
    595	{ 0x3909, 0x00 },
    596	{ 0x3912, 0x00 },
    597	{ 0x3930, 0x00 },
    598	{ 0x3931, 0x00 },
    599	{ 0x3933, 0x00 },
    600	{ 0x3934, 0x00 },
    601	{ 0x3935, 0x00 },
    602	{ 0x3936, 0x00 },
    603	{ 0x3937, 0x00 },
    604	{ 0x30ac, 0x00 },
    605};
    606
    607static const struct imx319_reg mode_1936x1096_regs[] = {
    608	{ 0x0112, 0x0a },
    609	{ 0x0113, 0x0a },
    610	{ 0x0114, 0x03 },
    611	{ 0x0342, 0x0f },
    612	{ 0x0343, 0x80 },
    613	{ 0x0340, 0x0c },
    614	{ 0x0341, 0xaa },
    615	{ 0x0344, 0x00 },
    616	{ 0x0345, 0x00 },
    617	{ 0x0346, 0x02 },
    618	{ 0x0347, 0xac },
    619	{ 0x0348, 0x0c },
    620	{ 0x0349, 0xcf },
    621	{ 0x034a, 0x06 },
    622	{ 0x034b, 0xf3 },
    623	{ 0x0220, 0x00 },
    624	{ 0x0221, 0x11 },
    625	{ 0x0381, 0x01 },
    626	{ 0x0383, 0x01 },
    627	{ 0x0385, 0x01 },
    628	{ 0x0387, 0x01 },
    629	{ 0x0900, 0x00 },
    630	{ 0x0901, 0x11 },
    631	{ 0x0902, 0x0a },
    632	{ 0x3140, 0x02 },
    633	{ 0x3141, 0x00 },
    634	{ 0x3f0d, 0x0a },
    635	{ 0x3f14, 0x01 },
    636	{ 0x3f3c, 0x01 },
    637	{ 0x3f4d, 0x01 },
    638	{ 0x3f4c, 0x01 },
    639	{ 0x4254, 0x7f },
    640	{ 0x0401, 0x00 },
    641	{ 0x0404, 0x00 },
    642	{ 0x0405, 0x10 },
    643	{ 0x0408, 0x02 },
    644	{ 0x0409, 0xa0 },
    645	{ 0x040a, 0x00 },
    646	{ 0x040b, 0x00 },
    647	{ 0x040c, 0x07 },
    648	{ 0x040d, 0x90 },
    649	{ 0x040e, 0x04 },
    650	{ 0x040f, 0x48 },
    651	{ 0x034c, 0x07 },
    652	{ 0x034d, 0x90 },
    653	{ 0x034e, 0x04 },
    654	{ 0x034f, 0x48 },
    655	{ 0x3261, 0x00 },
    656	{ 0x3264, 0x00 },
    657	{ 0x3265, 0x10 },
    658	{ 0x0301, 0x05 },
    659	{ 0x0303, 0x04 },
    660	{ 0x0305, 0x04 },
    661	{ 0x0306, 0x01 },
    662	{ 0x0307, 0x92 },
    663	{ 0x0309, 0x0a },
    664	{ 0x030b, 0x02 },
    665	{ 0x030d, 0x02 },
    666	{ 0x030e, 0x00 },
    667	{ 0x030f, 0xfa },
    668	{ 0x0310, 0x00 },
    669	{ 0x0820, 0x0f },
    670	{ 0x0821, 0x13 },
    671	{ 0x0822, 0x33 },
    672	{ 0x0823, 0x33 },
    673	{ 0x3e20, 0x01 },
    674	{ 0x3e37, 0x00 },
    675	{ 0x3e3b, 0x01 },
    676	{ 0x38a3, 0x01 },
    677	{ 0x38a8, 0x00 },
    678	{ 0x38a9, 0x00 },
    679	{ 0x38aa, 0x00 },
    680	{ 0x38ab, 0x00 },
    681	{ 0x3234, 0x00 },
    682	{ 0x3fc1, 0x00 },
    683	{ 0x3235, 0x00 },
    684	{ 0x3802, 0x00 },
    685	{ 0x3143, 0x04 },
    686	{ 0x360a, 0x00 },
    687	{ 0x0b00, 0x00 },
    688	{ 0x0106, 0x00 },
    689	{ 0x0b05, 0x01 },
    690	{ 0x0b06, 0x01 },
    691	{ 0x3230, 0x00 },
    692	{ 0x3602, 0x01 },
    693	{ 0x3607, 0x01 },
    694	{ 0x3c00, 0x00 },
    695	{ 0x3c01, 0x48 },
    696	{ 0x3c02, 0xc8 },
    697	{ 0x3c03, 0xaa },
    698	{ 0x3c04, 0x91 },
    699	{ 0x3c05, 0x54 },
    700	{ 0x3c06, 0x26 },
    701	{ 0x3c07, 0x20 },
    702	{ 0x3c08, 0x51 },
    703	{ 0x3d80, 0x00 },
    704	{ 0x3f50, 0x00 },
    705	{ 0x3f56, 0x00 },
    706	{ 0x3f57, 0x30 },
    707	{ 0x3f78, 0x01 },
    708	{ 0x3f79, 0x18 },
    709	{ 0x3f7c, 0x00 },
    710	{ 0x3f7d, 0x00 },
    711	{ 0x3fba, 0x00 },
    712	{ 0x3fbb, 0x00 },
    713	{ 0xa081, 0x00 },
    714	{ 0xe014, 0x00 },
    715	{ 0x0202, 0x05 },
    716	{ 0x0203, 0x34 },
    717	{ 0x0224, 0x01 },
    718	{ 0x0225, 0xf4 },
    719	{ 0x0204, 0x00 },
    720	{ 0x0205, 0x00 },
    721	{ 0x0216, 0x00 },
    722	{ 0x0217, 0x00 },
    723	{ 0x020e, 0x01 },
    724	{ 0x020f, 0x00 },
    725	{ 0x0210, 0x01 },
    726	{ 0x0211, 0x00 },
    727	{ 0x0212, 0x01 },
    728	{ 0x0213, 0x00 },
    729	{ 0x0214, 0x01 },
    730	{ 0x0215, 0x00 },
    731	{ 0x0218, 0x01 },
    732	{ 0x0219, 0x00 },
    733	{ 0x3614, 0x00 },
    734	{ 0x3616, 0x0d },
    735	{ 0x3617, 0x56 },
    736	{ 0xb612, 0x20 },
    737	{ 0xb613, 0x20 },
    738	{ 0xb614, 0x20 },
    739	{ 0xb615, 0x20 },
    740	{ 0xb616, 0x0a },
    741	{ 0xb617, 0x0a },
    742	{ 0xb618, 0x20 },
    743	{ 0xb619, 0x20 },
    744	{ 0xb61a, 0x20 },
    745	{ 0xb61b, 0x20 },
    746	{ 0xb61c, 0x0a },
    747	{ 0xb61d, 0x0a },
    748	{ 0xb666, 0x30 },
    749	{ 0xb667, 0x30 },
    750	{ 0xb668, 0x30 },
    751	{ 0xb669, 0x30 },
    752	{ 0xb66a, 0x14 },
    753	{ 0xb66b, 0x14 },
    754	{ 0xb66c, 0x20 },
    755	{ 0xb66d, 0x20 },
    756	{ 0xb66e, 0x20 },
    757	{ 0xb66f, 0x20 },
    758	{ 0xb670, 0x10 },
    759	{ 0xb671, 0x10 },
    760	{ 0x3237, 0x00 },
    761	{ 0x3900, 0x00 },
    762	{ 0x3901, 0x00 },
    763	{ 0x3902, 0x00 },
    764	{ 0x3904, 0x00 },
    765	{ 0x3905, 0x00 },
    766	{ 0x3906, 0x00 },
    767	{ 0x3907, 0x00 },
    768	{ 0x3908, 0x00 },
    769	{ 0x3909, 0x00 },
    770	{ 0x3912, 0x00 },
    771	{ 0x3930, 0x00 },
    772	{ 0x3931, 0x00 },
    773	{ 0x3933, 0x00 },
    774	{ 0x3934, 0x00 },
    775	{ 0x3935, 0x00 },
    776	{ 0x3936, 0x00 },
    777	{ 0x3937, 0x00 },
    778	{ 0x30ac, 0x00 },
    779};
    780
    781static const struct imx319_reg mode_1920x1080_regs[] = {
    782	{ 0x0112, 0x0a },
    783	{ 0x0113, 0x0a },
    784	{ 0x0114, 0x03 },
    785	{ 0x0342, 0x0f },
    786	{ 0x0343, 0x80 },
    787	{ 0x0340, 0x0c },
    788	{ 0x0341, 0xaa },
    789	{ 0x0344, 0x00 },
    790	{ 0x0345, 0x00 },
    791	{ 0x0346, 0x02 },
    792	{ 0x0347, 0xb4 },
    793	{ 0x0348, 0x0c },
    794	{ 0x0349, 0xcf },
    795	{ 0x034a, 0x06 },
    796	{ 0x034b, 0xeb },
    797	{ 0x0220, 0x00 },
    798	{ 0x0221, 0x11 },
    799	{ 0x0381, 0x01 },
    800	{ 0x0383, 0x01 },
    801	{ 0x0385, 0x01 },
    802	{ 0x0387, 0x01 },
    803	{ 0x0900, 0x00 },
    804	{ 0x0901, 0x11 },
    805	{ 0x0902, 0x0a },
    806	{ 0x3140, 0x02 },
    807	{ 0x3141, 0x00 },
    808	{ 0x3f0d, 0x0a },
    809	{ 0x3f14, 0x01 },
    810	{ 0x3f3c, 0x01 },
    811	{ 0x3f4d, 0x01 },
    812	{ 0x3f4c, 0x01 },
    813	{ 0x4254, 0x7f },
    814	{ 0x0401, 0x00 },
    815	{ 0x0404, 0x00 },
    816	{ 0x0405, 0x10 },
    817	{ 0x0408, 0x02 },
    818	{ 0x0409, 0xa8 },
    819	{ 0x040a, 0x00 },
    820	{ 0x040b, 0x00 },
    821	{ 0x040c, 0x07 },
    822	{ 0x040d, 0x80 },
    823	{ 0x040e, 0x04 },
    824	{ 0x040f, 0x38 },
    825	{ 0x034c, 0x07 },
    826	{ 0x034d, 0x80 },
    827	{ 0x034e, 0x04 },
    828	{ 0x034f, 0x38 },
    829	{ 0x3261, 0x00 },
    830	{ 0x3264, 0x00 },
    831	{ 0x3265, 0x10 },
    832	{ 0x0301, 0x05 },
    833	{ 0x0303, 0x04 },
    834	{ 0x0305, 0x04 },
    835	{ 0x0306, 0x01 },
    836	{ 0x0307, 0x92 },
    837	{ 0x0309, 0x0a },
    838	{ 0x030b, 0x02 },
    839	{ 0x030d, 0x02 },
    840	{ 0x030e, 0x00 },
    841	{ 0x030f, 0xfa },
    842	{ 0x0310, 0x00 },
    843	{ 0x0820, 0x0f },
    844	{ 0x0821, 0x13 },
    845	{ 0x0822, 0x33 },
    846	{ 0x0823, 0x33 },
    847	{ 0x3e20, 0x01 },
    848	{ 0x3e37, 0x00 },
    849	{ 0x3e3b, 0x01 },
    850	{ 0x38a3, 0x01 },
    851	{ 0x38a8, 0x00 },
    852	{ 0x38a9, 0x00 },
    853	{ 0x38aa, 0x00 },
    854	{ 0x38ab, 0x00 },
    855	{ 0x3234, 0x00 },
    856	{ 0x3fc1, 0x00 },
    857	{ 0x3235, 0x00 },
    858	{ 0x3802, 0x00 },
    859	{ 0x3143, 0x04 },
    860	{ 0x360a, 0x00 },
    861	{ 0x0b00, 0x00 },
    862	{ 0x0106, 0x00 },
    863	{ 0x0b05, 0x01 },
    864	{ 0x0b06, 0x01 },
    865	{ 0x3230, 0x00 },
    866	{ 0x3602, 0x01 },
    867	{ 0x3607, 0x01 },
    868	{ 0x3c00, 0x00 },
    869	{ 0x3c01, 0x48 },
    870	{ 0x3c02, 0xc8 },
    871	{ 0x3c03, 0xaa },
    872	{ 0x3c04, 0x91 },
    873	{ 0x3c05, 0x54 },
    874	{ 0x3c06, 0x26 },
    875	{ 0x3c07, 0x20 },
    876	{ 0x3c08, 0x51 },
    877	{ 0x3d80, 0x00 },
    878	{ 0x3f50, 0x00 },
    879	{ 0x3f56, 0x00 },
    880	{ 0x3f57, 0x30 },
    881	{ 0x3f78, 0x01 },
    882	{ 0x3f79, 0x18 },
    883	{ 0x3f7c, 0x00 },
    884	{ 0x3f7d, 0x00 },
    885	{ 0x3fba, 0x00 },
    886	{ 0x3fbb, 0x00 },
    887	{ 0xa081, 0x00 },
    888	{ 0xe014, 0x00 },
    889	{ 0x0202, 0x05 },
    890	{ 0x0203, 0x34 },
    891	{ 0x0224, 0x01 },
    892	{ 0x0225, 0xf4 },
    893	{ 0x0204, 0x00 },
    894	{ 0x0205, 0x00 },
    895	{ 0x0216, 0x00 },
    896	{ 0x0217, 0x00 },
    897	{ 0x020e, 0x01 },
    898	{ 0x020f, 0x00 },
    899	{ 0x0210, 0x01 },
    900	{ 0x0211, 0x00 },
    901	{ 0x0212, 0x01 },
    902	{ 0x0213, 0x00 },
    903	{ 0x0214, 0x01 },
    904	{ 0x0215, 0x00 },
    905	{ 0x0218, 0x01 },
    906	{ 0x0219, 0x00 },
    907	{ 0x3614, 0x00 },
    908	{ 0x3616, 0x0d },
    909	{ 0x3617, 0x56 },
    910	{ 0xb612, 0x20 },
    911	{ 0xb613, 0x20 },
    912	{ 0xb614, 0x20 },
    913	{ 0xb615, 0x20 },
    914	{ 0xb616, 0x0a },
    915	{ 0xb617, 0x0a },
    916	{ 0xb618, 0x20 },
    917	{ 0xb619, 0x20 },
    918	{ 0xb61a, 0x20 },
    919	{ 0xb61b, 0x20 },
    920	{ 0xb61c, 0x0a },
    921	{ 0xb61d, 0x0a },
    922	{ 0xb666, 0x30 },
    923	{ 0xb667, 0x30 },
    924	{ 0xb668, 0x30 },
    925	{ 0xb669, 0x30 },
    926	{ 0xb66a, 0x14 },
    927	{ 0xb66b, 0x14 },
    928	{ 0xb66c, 0x20 },
    929	{ 0xb66d, 0x20 },
    930	{ 0xb66e, 0x20 },
    931	{ 0xb66f, 0x20 },
    932	{ 0xb670, 0x10 },
    933	{ 0xb671, 0x10 },
    934	{ 0x3237, 0x00 },
    935	{ 0x3900, 0x00 },
    936	{ 0x3901, 0x00 },
    937	{ 0x3902, 0x00 },
    938	{ 0x3904, 0x00 },
    939	{ 0x3905, 0x00 },
    940	{ 0x3906, 0x00 },
    941	{ 0x3907, 0x00 },
    942	{ 0x3908, 0x00 },
    943	{ 0x3909, 0x00 },
    944	{ 0x3912, 0x00 },
    945	{ 0x3930, 0x00 },
    946	{ 0x3931, 0x00 },
    947	{ 0x3933, 0x00 },
    948	{ 0x3934, 0x00 },
    949	{ 0x3935, 0x00 },
    950	{ 0x3936, 0x00 },
    951	{ 0x3937, 0x00 },
    952	{ 0x30ac, 0x00 },
    953};
    954
    955static const struct imx319_reg mode_1640x1232_regs[] = {
    956	{ 0x0112, 0x0a },
    957	{ 0x0113, 0x0a },
    958	{ 0x0114, 0x03 },
    959	{ 0x0342, 0x08 },
    960	{ 0x0343, 0x20 },
    961	{ 0x0340, 0x18 },
    962	{ 0x0341, 0x2a },
    963	{ 0x0344, 0x00 },
    964	{ 0x0345, 0x00 },
    965	{ 0x0346, 0x00 },
    966	{ 0x0347, 0x00 },
    967	{ 0x0348, 0x0c },
    968	{ 0x0349, 0xcf },
    969	{ 0x034a, 0x09 },
    970	{ 0x034b, 0x9f },
    971	{ 0x0220, 0x00 },
    972	{ 0x0221, 0x11 },
    973	{ 0x0381, 0x01 },
    974	{ 0x0383, 0x01 },
    975	{ 0x0385, 0x01 },
    976	{ 0x0387, 0x01 },
    977	{ 0x0900, 0x01 },
    978	{ 0x0901, 0x22 },
    979	{ 0x0902, 0x0a },
    980	{ 0x3140, 0x02 },
    981	{ 0x3141, 0x00 },
    982	{ 0x3f0d, 0x0a },
    983	{ 0x3f14, 0x01 },
    984	{ 0x3f3c, 0x02 },
    985	{ 0x3f4d, 0x01 },
    986	{ 0x3f4c, 0x01 },
    987	{ 0x4254, 0x7f },
    988	{ 0x0401, 0x00 },
    989	{ 0x0404, 0x00 },
    990	{ 0x0405, 0x10 },
    991	{ 0x0408, 0x00 },
    992	{ 0x0409, 0x00 },
    993	{ 0x040a, 0x00 },
    994	{ 0x040b, 0x00 },
    995	{ 0x040c, 0x06 },
    996	{ 0x040d, 0x68 },
    997	{ 0x040e, 0x04 },
    998	{ 0x040f, 0xd0 },
    999	{ 0x034c, 0x06 },
   1000	{ 0x034d, 0x68 },
   1001	{ 0x034e, 0x04 },
   1002	{ 0x034f, 0xd0 },
   1003	{ 0x3261, 0x00 },
   1004	{ 0x3264, 0x00 },
   1005	{ 0x3265, 0x10 },
   1006	{ 0x0301, 0x05 },
   1007	{ 0x0303, 0x04 },
   1008	{ 0x0305, 0x04 },
   1009	{ 0x0306, 0x01 },
   1010	{ 0x0307, 0x92 },
   1011	{ 0x0309, 0x0a },
   1012	{ 0x030b, 0x02 },
   1013	{ 0x030d, 0x02 },
   1014	{ 0x030e, 0x00 },
   1015	{ 0x030f, 0xfa },
   1016	{ 0x0310, 0x00 },
   1017	{ 0x0820, 0x0f },
   1018	{ 0x0821, 0x13 },
   1019	{ 0x0822, 0x33 },
   1020	{ 0x0823, 0x33 },
   1021	{ 0x3e20, 0x01 },
   1022	{ 0x3e37, 0x00 },
   1023	{ 0x3e3b, 0x01 },
   1024	{ 0x38a3, 0x01 },
   1025	{ 0x38a8, 0x00 },
   1026	{ 0x38a9, 0x00 },
   1027	{ 0x38aa, 0x00 },
   1028	{ 0x38ab, 0x00 },
   1029	{ 0x3234, 0x00 },
   1030	{ 0x3fc1, 0x00 },
   1031	{ 0x3235, 0x00 },
   1032	{ 0x3802, 0x00 },
   1033	{ 0x3143, 0x04 },
   1034	{ 0x360a, 0x00 },
   1035	{ 0x0b00, 0x00 },
   1036	{ 0x0106, 0x00 },
   1037	{ 0x0b05, 0x01 },
   1038	{ 0x0b06, 0x01 },
   1039	{ 0x3230, 0x00 },
   1040	{ 0x3602, 0x01 },
   1041	{ 0x3607, 0x01 },
   1042	{ 0x3c00, 0x00 },
   1043	{ 0x3c01, 0xba },
   1044	{ 0x3c02, 0xc8 },
   1045	{ 0x3c03, 0xaa },
   1046	{ 0x3c04, 0x91 },
   1047	{ 0x3c05, 0x54 },
   1048	{ 0x3c06, 0x26 },
   1049	{ 0x3c07, 0x20 },
   1050	{ 0x3c08, 0x51 },
   1051	{ 0x3d80, 0x00 },
   1052	{ 0x3f50, 0x00 },
   1053	{ 0x3f56, 0x00 },
   1054	{ 0x3f57, 0x30 },
   1055	{ 0x3f78, 0x00 },
   1056	{ 0x3f79, 0x34 },
   1057	{ 0x3f7c, 0x00 },
   1058	{ 0x3f7d, 0x00 },
   1059	{ 0x3fba, 0x00 },
   1060	{ 0x3fbb, 0x00 },
   1061	{ 0xa081, 0x04 },
   1062	{ 0xe014, 0x00 },
   1063	{ 0x0202, 0x04 },
   1064	{ 0x0203, 0xf6 },
   1065	{ 0x0224, 0x01 },
   1066	{ 0x0225, 0xf4 },
   1067	{ 0x0204, 0x00 },
   1068	{ 0x0205, 0x00 },
   1069	{ 0x0216, 0x00 },
   1070	{ 0x0217, 0x00 },
   1071	{ 0x020e, 0x01 },
   1072	{ 0x020f, 0x00 },
   1073	{ 0x0210, 0x01 },
   1074	{ 0x0211, 0x00 },
   1075	{ 0x0212, 0x01 },
   1076	{ 0x0213, 0x00 },
   1077	{ 0x0214, 0x01 },
   1078	{ 0x0215, 0x00 },
   1079	{ 0x0218, 0x01 },
   1080	{ 0x0219, 0x00 },
   1081	{ 0x3614, 0x00 },
   1082	{ 0x3616, 0x0d },
   1083	{ 0x3617, 0x56 },
   1084	{ 0xb612, 0x20 },
   1085	{ 0xb613, 0x20 },
   1086	{ 0xb614, 0x20 },
   1087	{ 0xb615, 0x20 },
   1088	{ 0xb616, 0x0a },
   1089	{ 0xb617, 0x0a },
   1090	{ 0xb618, 0x20 },
   1091	{ 0xb619, 0x20 },
   1092	{ 0xb61a, 0x20 },
   1093	{ 0xb61b, 0x20 },
   1094	{ 0xb61c, 0x0a },
   1095	{ 0xb61d, 0x0a },
   1096	{ 0xb666, 0x30 },
   1097	{ 0xb667, 0x30 },
   1098	{ 0xb668, 0x30 },
   1099	{ 0xb669, 0x30 },
   1100	{ 0xb66a, 0x14 },
   1101	{ 0xb66b, 0x14 },
   1102	{ 0xb66c, 0x20 },
   1103	{ 0xb66d, 0x20 },
   1104	{ 0xb66e, 0x20 },
   1105	{ 0xb66f, 0x20 },
   1106	{ 0xb670, 0x10 },
   1107	{ 0xb671, 0x10 },
   1108	{ 0x3237, 0x00 },
   1109	{ 0x3900, 0x00 },
   1110	{ 0x3901, 0x00 },
   1111	{ 0x3902, 0x00 },
   1112	{ 0x3904, 0x00 },
   1113	{ 0x3905, 0x00 },
   1114	{ 0x3906, 0x00 },
   1115	{ 0x3907, 0x00 },
   1116	{ 0x3908, 0x00 },
   1117	{ 0x3909, 0x00 },
   1118	{ 0x3912, 0x00 },
   1119	{ 0x3930, 0x00 },
   1120	{ 0x3931, 0x00 },
   1121	{ 0x3933, 0x00 },
   1122	{ 0x3934, 0x00 },
   1123	{ 0x3935, 0x00 },
   1124	{ 0x3936, 0x00 },
   1125	{ 0x3937, 0x00 },
   1126	{ 0x30ac, 0x00 },
   1127};
   1128
   1129static const struct imx319_reg mode_1640x922_regs[] = {
   1130	{ 0x0112, 0x0a },
   1131	{ 0x0113, 0x0a },
   1132	{ 0x0114, 0x03 },
   1133	{ 0x0342, 0x08 },
   1134	{ 0x0343, 0x20 },
   1135	{ 0x0340, 0x18 },
   1136	{ 0x0341, 0x2a },
   1137	{ 0x0344, 0x00 },
   1138	{ 0x0345, 0x00 },
   1139	{ 0x0346, 0x01 },
   1140	{ 0x0347, 0x30 },
   1141	{ 0x0348, 0x0c },
   1142	{ 0x0349, 0xcf },
   1143	{ 0x034a, 0x08 },
   1144	{ 0x034b, 0x6f },
   1145	{ 0x0220, 0x00 },
   1146	{ 0x0221, 0x11 },
   1147	{ 0x0381, 0x01 },
   1148	{ 0x0383, 0x01 },
   1149	{ 0x0385, 0x01 },
   1150	{ 0x0387, 0x01 },
   1151	{ 0x0900, 0x01 },
   1152	{ 0x0901, 0x22 },
   1153	{ 0x0902, 0x0a },
   1154	{ 0x3140, 0x02 },
   1155	{ 0x3141, 0x00 },
   1156	{ 0x3f0d, 0x0a },
   1157	{ 0x3f14, 0x01 },
   1158	{ 0x3f3c, 0x02 },
   1159	{ 0x3f4d, 0x01 },
   1160	{ 0x3f4c, 0x01 },
   1161	{ 0x4254, 0x7f },
   1162	{ 0x0401, 0x00 },
   1163	{ 0x0404, 0x00 },
   1164	{ 0x0405, 0x10 },
   1165	{ 0x0408, 0x00 },
   1166	{ 0x0409, 0x00 },
   1167	{ 0x040a, 0x00 },
   1168	{ 0x040b, 0x02 },
   1169	{ 0x040c, 0x06 },
   1170	{ 0x040d, 0x68 },
   1171	{ 0x040e, 0x03 },
   1172	{ 0x040f, 0x9a },
   1173	{ 0x034c, 0x06 },
   1174	{ 0x034d, 0x68 },
   1175	{ 0x034e, 0x03 },
   1176	{ 0x034f, 0x9a },
   1177	{ 0x3261, 0x00 },
   1178	{ 0x3264, 0x00 },
   1179	{ 0x3265, 0x10 },
   1180	{ 0x0301, 0x05 },
   1181	{ 0x0303, 0x04 },
   1182	{ 0x0305, 0x04 },
   1183	{ 0x0306, 0x01 },
   1184	{ 0x0307, 0x92 },
   1185	{ 0x0309, 0x0a },
   1186	{ 0x030b, 0x02 },
   1187	{ 0x030d, 0x02 },
   1188	{ 0x030e, 0x00 },
   1189	{ 0x030f, 0xfa },
   1190	{ 0x0310, 0x00 },
   1191	{ 0x0820, 0x0f },
   1192	{ 0x0821, 0x13 },
   1193	{ 0x0822, 0x33 },
   1194	{ 0x0823, 0x33 },
   1195	{ 0x3e20, 0x01 },
   1196	{ 0x3e37, 0x00 },
   1197	{ 0x3e3b, 0x01 },
   1198	{ 0x38a3, 0x01 },
   1199	{ 0x38a8, 0x00 },
   1200	{ 0x38a9, 0x00 },
   1201	{ 0x38aa, 0x00 },
   1202	{ 0x38ab, 0x00 },
   1203	{ 0x3234, 0x00 },
   1204	{ 0x3fc1, 0x00 },
   1205	{ 0x3235, 0x00 },
   1206	{ 0x3802, 0x00 },
   1207	{ 0x3143, 0x04 },
   1208	{ 0x360a, 0x00 },
   1209	{ 0x0b00, 0x00 },
   1210	{ 0x0106, 0x00 },
   1211	{ 0x0b05, 0x01 },
   1212	{ 0x0b06, 0x01 },
   1213	{ 0x3230, 0x00 },
   1214	{ 0x3602, 0x01 },
   1215	{ 0x3607, 0x01 },
   1216	{ 0x3c00, 0x00 },
   1217	{ 0x3c01, 0xba },
   1218	{ 0x3c02, 0xc8 },
   1219	{ 0x3c03, 0xaa },
   1220	{ 0x3c04, 0x91 },
   1221	{ 0x3c05, 0x54 },
   1222	{ 0x3c06, 0x26 },
   1223	{ 0x3c07, 0x20 },
   1224	{ 0x3c08, 0x51 },
   1225	{ 0x3d80, 0x00 },
   1226	{ 0x3f50, 0x00 },
   1227	{ 0x3f56, 0x00 },
   1228	{ 0x3f57, 0x30 },
   1229	{ 0x3f78, 0x00 },
   1230	{ 0x3f79, 0x34 },
   1231	{ 0x3f7c, 0x00 },
   1232	{ 0x3f7d, 0x00 },
   1233	{ 0x3fba, 0x00 },
   1234	{ 0x3fbb, 0x00 },
   1235	{ 0xa081, 0x04 },
   1236	{ 0xe014, 0x00 },
   1237	{ 0x0202, 0x04 },
   1238	{ 0x0203, 0xf6 },
   1239	{ 0x0224, 0x01 },
   1240	{ 0x0225, 0xf4 },
   1241	{ 0x0204, 0x00 },
   1242	{ 0x0205, 0x00 },
   1243	{ 0x0216, 0x00 },
   1244	{ 0x0217, 0x00 },
   1245	{ 0x020e, 0x01 },
   1246	{ 0x020f, 0x00 },
   1247	{ 0x0210, 0x01 },
   1248	{ 0x0211, 0x00 },
   1249	{ 0x0212, 0x01 },
   1250	{ 0x0213, 0x00 },
   1251	{ 0x0214, 0x01 },
   1252	{ 0x0215, 0x00 },
   1253	{ 0x0218, 0x01 },
   1254	{ 0x0219, 0x00 },
   1255	{ 0x3614, 0x00 },
   1256	{ 0x3616, 0x0d },
   1257	{ 0x3617, 0x56 },
   1258	{ 0xb612, 0x20 },
   1259	{ 0xb613, 0x20 },
   1260	{ 0xb614, 0x20 },
   1261	{ 0xb615, 0x20 },
   1262	{ 0xb616, 0x0a },
   1263	{ 0xb617, 0x0a },
   1264	{ 0xb618, 0x20 },
   1265	{ 0xb619, 0x20 },
   1266	{ 0xb61a, 0x20 },
   1267	{ 0xb61b, 0x20 },
   1268	{ 0xb61c, 0x0a },
   1269	{ 0xb61d, 0x0a },
   1270	{ 0xb666, 0x30 },
   1271	{ 0xb667, 0x30 },
   1272	{ 0xb668, 0x30 },
   1273	{ 0xb669, 0x30 },
   1274	{ 0xb66a, 0x14 },
   1275	{ 0xb66b, 0x14 },
   1276	{ 0xb66c, 0x20 },
   1277	{ 0xb66d, 0x20 },
   1278	{ 0xb66e, 0x20 },
   1279	{ 0xb66f, 0x20 },
   1280	{ 0xb670, 0x10 },
   1281	{ 0xb671, 0x10 },
   1282	{ 0x3237, 0x00 },
   1283	{ 0x3900, 0x00 },
   1284	{ 0x3901, 0x00 },
   1285	{ 0x3902, 0x00 },
   1286	{ 0x3904, 0x00 },
   1287	{ 0x3905, 0x00 },
   1288	{ 0x3906, 0x00 },
   1289	{ 0x3907, 0x00 },
   1290	{ 0x3908, 0x00 },
   1291	{ 0x3909, 0x00 },
   1292	{ 0x3912, 0x00 },
   1293	{ 0x3930, 0x00 },
   1294	{ 0x3931, 0x00 },
   1295	{ 0x3933, 0x00 },
   1296	{ 0x3934, 0x00 },
   1297	{ 0x3935, 0x00 },
   1298	{ 0x3936, 0x00 },
   1299	{ 0x3937, 0x00 },
   1300	{ 0x30ac, 0x00 },
   1301};
   1302
   1303static const struct imx319_reg mode_1296x736_regs[] = {
   1304	{ 0x0112, 0x0a },
   1305	{ 0x0113, 0x0a },
   1306	{ 0x0114, 0x03 },
   1307	{ 0x0342, 0x08 },
   1308	{ 0x0343, 0x20 },
   1309	{ 0x0340, 0x18 },
   1310	{ 0x0341, 0x2a },
   1311	{ 0x0344, 0x00 },
   1312	{ 0x0345, 0x00 },
   1313	{ 0x0346, 0x01 },
   1314	{ 0x0347, 0xf0 },
   1315	{ 0x0348, 0x0c },
   1316	{ 0x0349, 0xcf },
   1317	{ 0x034a, 0x07 },
   1318	{ 0x034b, 0xaf },
   1319	{ 0x0220, 0x00 },
   1320	{ 0x0221, 0x11 },
   1321	{ 0x0381, 0x01 },
   1322	{ 0x0383, 0x01 },
   1323	{ 0x0385, 0x01 },
   1324	{ 0x0387, 0x01 },
   1325	{ 0x0900, 0x01 },
   1326	{ 0x0901, 0x22 },
   1327	{ 0x0902, 0x0a },
   1328	{ 0x3140, 0x02 },
   1329	{ 0x3141, 0x00 },
   1330	{ 0x3f0d, 0x0a },
   1331	{ 0x3f14, 0x01 },
   1332	{ 0x3f3c, 0x02 },
   1333	{ 0x3f4d, 0x01 },
   1334	{ 0x3f4c, 0x01 },
   1335	{ 0x4254, 0x7f },
   1336	{ 0x0401, 0x00 },
   1337	{ 0x0404, 0x00 },
   1338	{ 0x0405, 0x10 },
   1339	{ 0x0408, 0x00 },
   1340	{ 0x0409, 0xac },
   1341	{ 0x040a, 0x00 },
   1342	{ 0x040b, 0x00 },
   1343	{ 0x040c, 0x05 },
   1344	{ 0x040d, 0x10 },
   1345	{ 0x040e, 0x02 },
   1346	{ 0x040f, 0xe0 },
   1347	{ 0x034c, 0x05 },
   1348	{ 0x034d, 0x10 },
   1349	{ 0x034e, 0x02 },
   1350	{ 0x034f, 0xe0 },
   1351	{ 0x3261, 0x00 },
   1352	{ 0x3264, 0x00 },
   1353	{ 0x3265, 0x10 },
   1354	{ 0x0301, 0x05 },
   1355	{ 0x0303, 0x04 },
   1356	{ 0x0305, 0x04 },
   1357	{ 0x0306, 0x01 },
   1358	{ 0x0307, 0x92 },
   1359	{ 0x0309, 0x0a },
   1360	{ 0x030b, 0x02 },
   1361	{ 0x030d, 0x02 },
   1362	{ 0x030e, 0x00 },
   1363	{ 0x030f, 0xfa },
   1364	{ 0x0310, 0x00 },
   1365	{ 0x0820, 0x0f },
   1366	{ 0x0821, 0x13 },
   1367	{ 0x0822, 0x33 },
   1368	{ 0x0823, 0x33 },
   1369	{ 0x3e20, 0x01 },
   1370	{ 0x3e37, 0x00 },
   1371	{ 0x3e3b, 0x01 },
   1372	{ 0x38a3, 0x01 },
   1373	{ 0x38a8, 0x00 },
   1374	{ 0x38a9, 0x00 },
   1375	{ 0x38aa, 0x00 },
   1376	{ 0x38ab, 0x00 },
   1377	{ 0x3234, 0x00 },
   1378	{ 0x3fc1, 0x00 },
   1379	{ 0x3235, 0x00 },
   1380	{ 0x3802, 0x00 },
   1381	{ 0x3143, 0x04 },
   1382	{ 0x360a, 0x00 },
   1383	{ 0x0b00, 0x00 },
   1384	{ 0x0106, 0x00 },
   1385	{ 0x0b05, 0x01 },
   1386	{ 0x0b06, 0x01 },
   1387	{ 0x3230, 0x00 },
   1388	{ 0x3602, 0x01 },
   1389	{ 0x3607, 0x01 },
   1390	{ 0x3c00, 0x00 },
   1391	{ 0x3c01, 0xba },
   1392	{ 0x3c02, 0xc8 },
   1393	{ 0x3c03, 0xaa },
   1394	{ 0x3c04, 0x91 },
   1395	{ 0x3c05, 0x54 },
   1396	{ 0x3c06, 0x26 },
   1397	{ 0x3c07, 0x20 },
   1398	{ 0x3c08, 0x51 },
   1399	{ 0x3d80, 0x00 },
   1400	{ 0x3f50, 0x00 },
   1401	{ 0x3f56, 0x00 },
   1402	{ 0x3f57, 0x30 },
   1403	{ 0x3f78, 0x00 },
   1404	{ 0x3f79, 0x34 },
   1405	{ 0x3f7c, 0x00 },
   1406	{ 0x3f7d, 0x00 },
   1407	{ 0x3fba, 0x00 },
   1408	{ 0x3fbb, 0x00 },
   1409	{ 0xa081, 0x04 },
   1410	{ 0xe014, 0x00 },
   1411	{ 0x0202, 0x04 },
   1412	{ 0x0203, 0xf6 },
   1413	{ 0x0224, 0x01 },
   1414	{ 0x0225, 0xf4 },
   1415	{ 0x0204, 0x00 },
   1416	{ 0x0205, 0x00 },
   1417	{ 0x0216, 0x00 },
   1418	{ 0x0217, 0x00 },
   1419	{ 0x020e, 0x01 },
   1420	{ 0x020f, 0x00 },
   1421	{ 0x0210, 0x01 },
   1422	{ 0x0211, 0x00 },
   1423	{ 0x0212, 0x01 },
   1424	{ 0x0213, 0x00 },
   1425	{ 0x0214, 0x01 },
   1426	{ 0x0215, 0x00 },
   1427	{ 0x0218, 0x01 },
   1428	{ 0x0219, 0x00 },
   1429	{ 0x3614, 0x00 },
   1430	{ 0x3616, 0x0d },
   1431	{ 0x3617, 0x56 },
   1432	{ 0xb612, 0x20 },
   1433	{ 0xb613, 0x20 },
   1434	{ 0xb614, 0x20 },
   1435	{ 0xb615, 0x20 },
   1436	{ 0xb616, 0x0a },
   1437	{ 0xb617, 0x0a },
   1438	{ 0xb618, 0x20 },
   1439	{ 0xb619, 0x20 },
   1440	{ 0xb61a, 0x20 },
   1441	{ 0xb61b, 0x20 },
   1442	{ 0xb61c, 0x0a },
   1443	{ 0xb61d, 0x0a },
   1444	{ 0xb666, 0x30 },
   1445	{ 0xb667, 0x30 },
   1446	{ 0xb668, 0x30 },
   1447	{ 0xb669, 0x30 },
   1448	{ 0xb66a, 0x14 },
   1449	{ 0xb66b, 0x14 },
   1450	{ 0xb66c, 0x20 },
   1451	{ 0xb66d, 0x20 },
   1452	{ 0xb66e, 0x20 },
   1453	{ 0xb66f, 0x20 },
   1454	{ 0xb670, 0x10 },
   1455	{ 0xb671, 0x10 },
   1456	{ 0x3237, 0x00 },
   1457	{ 0x3900, 0x00 },
   1458	{ 0x3901, 0x00 },
   1459	{ 0x3902, 0x00 },
   1460	{ 0x3904, 0x00 },
   1461	{ 0x3905, 0x00 },
   1462	{ 0x3906, 0x00 },
   1463	{ 0x3907, 0x00 },
   1464	{ 0x3908, 0x00 },
   1465	{ 0x3909, 0x00 },
   1466	{ 0x3912, 0x00 },
   1467	{ 0x3930, 0x00 },
   1468	{ 0x3931, 0x00 },
   1469	{ 0x3933, 0x00 },
   1470	{ 0x3934, 0x00 },
   1471	{ 0x3935, 0x00 },
   1472	{ 0x3936, 0x00 },
   1473	{ 0x3937, 0x00 },
   1474	{ 0x30ac, 0x00 },
   1475};
   1476
   1477static const struct imx319_reg mode_1280x720_regs[] = {
   1478	{ 0x0112, 0x0a },
   1479	{ 0x0113, 0x0a },
   1480	{ 0x0114, 0x03 },
   1481	{ 0x0342, 0x08 },
   1482	{ 0x0343, 0x20 },
   1483	{ 0x0340, 0x18 },
   1484	{ 0x0341, 0x2a },
   1485	{ 0x0344, 0x00 },
   1486	{ 0x0345, 0x00 },
   1487	{ 0x0346, 0x02 },
   1488	{ 0x0347, 0x00 },
   1489	{ 0x0348, 0x0c },
   1490	{ 0x0349, 0xcf },
   1491	{ 0x034a, 0x07 },
   1492	{ 0x034b, 0x9f },
   1493	{ 0x0220, 0x00 },
   1494	{ 0x0221, 0x11 },
   1495	{ 0x0381, 0x01 },
   1496	{ 0x0383, 0x01 },
   1497	{ 0x0385, 0x01 },
   1498	{ 0x0387, 0x01 },
   1499	{ 0x0900, 0x01 },
   1500	{ 0x0901, 0x22 },
   1501	{ 0x0902, 0x0a },
   1502	{ 0x3140, 0x02 },
   1503	{ 0x3141, 0x00 },
   1504	{ 0x3f0d, 0x0a },
   1505	{ 0x3f14, 0x01 },
   1506	{ 0x3f3c, 0x02 },
   1507	{ 0x3f4d, 0x01 },
   1508	{ 0x3f4c, 0x01 },
   1509	{ 0x4254, 0x7f },
   1510	{ 0x0401, 0x00 },
   1511	{ 0x0404, 0x00 },
   1512	{ 0x0405, 0x10 },
   1513	{ 0x0408, 0x00 },
   1514	{ 0x0409, 0xb4 },
   1515	{ 0x040a, 0x00 },
   1516	{ 0x040b, 0x00 },
   1517	{ 0x040c, 0x05 },
   1518	{ 0x040d, 0x00 },
   1519	{ 0x040e, 0x02 },
   1520	{ 0x040f, 0xd0 },
   1521	{ 0x034c, 0x05 },
   1522	{ 0x034d, 0x00 },
   1523	{ 0x034e, 0x02 },
   1524	{ 0x034f, 0xd0 },
   1525	{ 0x3261, 0x00 },
   1526	{ 0x3264, 0x00 },
   1527	{ 0x3265, 0x10 },
   1528	{ 0x0301, 0x05 },
   1529	{ 0x0303, 0x04 },
   1530	{ 0x0305, 0x04 },
   1531	{ 0x0306, 0x01 },
   1532	{ 0x0307, 0x92 },
   1533	{ 0x0309, 0x0a },
   1534	{ 0x030b, 0x02 },
   1535	{ 0x030d, 0x02 },
   1536	{ 0x030e, 0x00 },
   1537	{ 0x030f, 0xfa },
   1538	{ 0x0310, 0x00 },
   1539	{ 0x0820, 0x0f },
   1540	{ 0x0821, 0x13 },
   1541	{ 0x0822, 0x33 },
   1542	{ 0x0823, 0x33 },
   1543	{ 0x3e20, 0x01 },
   1544	{ 0x3e37, 0x00 },
   1545	{ 0x3e3b, 0x01 },
   1546	{ 0x38a3, 0x01 },
   1547	{ 0x38a8, 0x00 },
   1548	{ 0x38a9, 0x00 },
   1549	{ 0x38aa, 0x00 },
   1550	{ 0x38ab, 0x00 },
   1551	{ 0x3234, 0x00 },
   1552	{ 0x3fc1, 0x00 },
   1553	{ 0x3235, 0x00 },
   1554	{ 0x3802, 0x00 },
   1555	{ 0x3143, 0x04 },
   1556	{ 0x360a, 0x00 },
   1557	{ 0x0b00, 0x00 },
   1558	{ 0x0106, 0x00 },
   1559	{ 0x0b05, 0x01 },
   1560	{ 0x0b06, 0x01 },
   1561	{ 0x3230, 0x00 },
   1562	{ 0x3602, 0x01 },
   1563	{ 0x3607, 0x01 },
   1564	{ 0x3c00, 0x00 },
   1565	{ 0x3c01, 0xba },
   1566	{ 0x3c02, 0xc8 },
   1567	{ 0x3c03, 0xaa },
   1568	{ 0x3c04, 0x91 },
   1569	{ 0x3c05, 0x54 },
   1570	{ 0x3c06, 0x26 },
   1571	{ 0x3c07, 0x20 },
   1572	{ 0x3c08, 0x51 },
   1573	{ 0x3d80, 0x00 },
   1574	{ 0x3f50, 0x00 },
   1575	{ 0x3f56, 0x00 },
   1576	{ 0x3f57, 0x30 },
   1577	{ 0x3f78, 0x00 },
   1578	{ 0x3f79, 0x34 },
   1579	{ 0x3f7c, 0x00 },
   1580	{ 0x3f7d, 0x00 },
   1581	{ 0x3fba, 0x00 },
   1582	{ 0x3fbb, 0x00 },
   1583	{ 0xa081, 0x04 },
   1584	{ 0xe014, 0x00 },
   1585	{ 0x0202, 0x04 },
   1586	{ 0x0203, 0xf6 },
   1587	{ 0x0224, 0x01 },
   1588	{ 0x0225, 0xf4 },
   1589	{ 0x0204, 0x00 },
   1590	{ 0x0205, 0x00 },
   1591	{ 0x0216, 0x00 },
   1592	{ 0x0217, 0x00 },
   1593	{ 0x020e, 0x01 },
   1594	{ 0x020f, 0x00 },
   1595	{ 0x0210, 0x01 },
   1596	{ 0x0211, 0x00 },
   1597	{ 0x0212, 0x01 },
   1598	{ 0x0213, 0x00 },
   1599	{ 0x0214, 0x01 },
   1600	{ 0x0215, 0x00 },
   1601	{ 0x0218, 0x01 },
   1602	{ 0x0219, 0x00 },
   1603	{ 0x3614, 0x00 },
   1604	{ 0x3616, 0x0d },
   1605	{ 0x3617, 0x56 },
   1606	{ 0xb612, 0x20 },
   1607	{ 0xb613, 0x20 },
   1608	{ 0xb614, 0x20 },
   1609	{ 0xb615, 0x20 },
   1610	{ 0xb616, 0x0a },
   1611	{ 0xb617, 0x0a },
   1612	{ 0xb618, 0x20 },
   1613	{ 0xb619, 0x20 },
   1614	{ 0xb61a, 0x20 },
   1615	{ 0xb61b, 0x20 },
   1616	{ 0xb61c, 0x0a },
   1617	{ 0xb61d, 0x0a },
   1618	{ 0xb666, 0x30 },
   1619	{ 0xb667, 0x30 },
   1620	{ 0xb668, 0x30 },
   1621	{ 0xb669, 0x30 },
   1622	{ 0xb66a, 0x14 },
   1623	{ 0xb66b, 0x14 },
   1624	{ 0xb66c, 0x20 },
   1625	{ 0xb66d, 0x20 },
   1626	{ 0xb66e, 0x20 },
   1627	{ 0xb66f, 0x20 },
   1628	{ 0xb670, 0x10 },
   1629	{ 0xb671, 0x10 },
   1630	{ 0x3237, 0x00 },
   1631	{ 0x3900, 0x00 },
   1632	{ 0x3901, 0x00 },
   1633	{ 0x3902, 0x00 },
   1634	{ 0x3904, 0x00 },
   1635	{ 0x3905, 0x00 },
   1636	{ 0x3906, 0x00 },
   1637	{ 0x3907, 0x00 },
   1638	{ 0x3908, 0x00 },
   1639	{ 0x3909, 0x00 },
   1640	{ 0x3912, 0x00 },
   1641	{ 0x3930, 0x00 },
   1642	{ 0x3931, 0x00 },
   1643	{ 0x3933, 0x00 },
   1644	{ 0x3934, 0x00 },
   1645	{ 0x3935, 0x00 },
   1646	{ 0x3936, 0x00 },
   1647	{ 0x3937, 0x00 },
   1648	{ 0x30ac, 0x00 },
   1649};
   1650
   1651static const char * const imx319_test_pattern_menu[] = {
   1652	"Disabled",
   1653	"Solid Colour",
   1654	"Eight Vertical Colour Bars",
   1655	"Colour Bars With Fade to Grey",
   1656	"Pseudorandom Sequence (PN9)",
   1657};
   1658
   1659/* supported link frequencies */
   1660static const s64 link_freq_menu_items[] = {
   1661	IMX319_LINK_FREQ_DEFAULT,
   1662};
   1663
   1664/* Mode configs */
   1665static const struct imx319_mode supported_modes[] = {
   1666	{
   1667		.width = 3280,
   1668		.height = 2464,
   1669		.fll_def = 3242,
   1670		.fll_min = 3242,
   1671		.llp = 3968,
   1672		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1673		.reg_list = {
   1674			.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
   1675			.regs = mode_3280x2464_regs,
   1676		},
   1677	},
   1678	{
   1679		.width = 3264,
   1680		.height = 2448,
   1681		.fll_def = 3242,
   1682		.fll_min = 3242,
   1683		.llp = 3968,
   1684		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1685		.reg_list = {
   1686			.num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
   1687			.regs = mode_3264x2448_regs,
   1688		},
   1689	},
   1690	{
   1691		.width = 1936,
   1692		.height = 1096,
   1693		.fll_def = 3242,
   1694		.fll_min = 3242,
   1695		.llp = 3968,
   1696		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1697		.reg_list = {
   1698			.num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),
   1699			.regs = mode_1936x1096_regs,
   1700		},
   1701	},
   1702	{
   1703		.width = 1920,
   1704		.height = 1080,
   1705		.fll_def = 3242,
   1706		.fll_min = 3242,
   1707		.llp = 3968,
   1708		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1709		.reg_list = {
   1710			.num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
   1711			.regs = mode_1920x1080_regs,
   1712		},
   1713	},
   1714	{
   1715		.width = 1640,
   1716		.height = 1232,
   1717		.fll_def = 5146,
   1718		.fll_min = 5146,
   1719		.llp = 2500,
   1720		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1721		.reg_list = {
   1722			.num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),
   1723			.regs = mode_1640x1232_regs,
   1724		},
   1725	},
   1726	{
   1727		.width = 1640,
   1728		.height = 922,
   1729		.fll_def = 5146,
   1730		.fll_min = 5146,
   1731		.llp = 2500,
   1732		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1733		.reg_list = {
   1734			.num_of_regs = ARRAY_SIZE(mode_1640x922_regs),
   1735			.regs = mode_1640x922_regs,
   1736		},
   1737	},
   1738	{
   1739		.width = 1296,
   1740		.height = 736,
   1741		.fll_def = 5146,
   1742		.fll_min = 5146,
   1743		.llp = 2500,
   1744		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1745		.reg_list = {
   1746			.num_of_regs = ARRAY_SIZE(mode_1296x736_regs),
   1747			.regs = mode_1296x736_regs,
   1748		},
   1749	},
   1750	{
   1751		.width = 1280,
   1752		.height = 720,
   1753		.fll_def = 5146,
   1754		.fll_min = 5146,
   1755		.llp = 2500,
   1756		.link_freq_index = IMX319_LINK_FREQ_INDEX,
   1757		.reg_list = {
   1758			.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
   1759			.regs = mode_1280x720_regs,
   1760		},
   1761	},
   1762};
   1763
   1764static inline struct imx319 *to_imx319(struct v4l2_subdev *_sd)
   1765{
   1766	return container_of(_sd, struct imx319, sd);
   1767}
   1768
   1769/* Get bayer order based on flip setting. */
   1770static u32 imx319_get_format_code(struct imx319 *imx319)
   1771{
   1772	/*
   1773	 * Only one bayer order is supported.
   1774	 * It depends on the flip settings.
   1775	 */
   1776	u32 code;
   1777	static const u32 codes[2][2] = {
   1778		{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
   1779		{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
   1780	};
   1781
   1782	lockdep_assert_held(&imx319->mutex);
   1783	code = codes[imx319->vflip->val][imx319->hflip->val];
   1784
   1785	return code;
   1786}
   1787
   1788/* Read registers up to 4 at a time */
   1789static int imx319_read_reg(struct imx319 *imx319, u16 reg, u32 len, u32 *val)
   1790{
   1791	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   1792	struct i2c_msg msgs[2];
   1793	u8 addr_buf[2];
   1794	u8 data_buf[4] = { 0 };
   1795	int ret;
   1796
   1797	if (len > 4)
   1798		return -EINVAL;
   1799
   1800	put_unaligned_be16(reg, addr_buf);
   1801	/* Write register address */
   1802	msgs[0].addr = client->addr;
   1803	msgs[0].flags = 0;
   1804	msgs[0].len = ARRAY_SIZE(addr_buf);
   1805	msgs[0].buf = addr_buf;
   1806
   1807	/* Read data from register */
   1808	msgs[1].addr = client->addr;
   1809	msgs[1].flags = I2C_M_RD;
   1810	msgs[1].len = len;
   1811	msgs[1].buf = &data_buf[4 - len];
   1812
   1813	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
   1814	if (ret != ARRAY_SIZE(msgs))
   1815		return -EIO;
   1816
   1817	*val = get_unaligned_be32(data_buf);
   1818
   1819	return 0;
   1820}
   1821
   1822/* Write registers up to 4 at a time */
   1823static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val)
   1824{
   1825	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   1826	u8 buf[6];
   1827
   1828	if (len > 4)
   1829		return -EINVAL;
   1830
   1831	put_unaligned_be16(reg, buf);
   1832	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
   1833	if (i2c_master_send(client, buf, len + 2) != len + 2)
   1834		return -EIO;
   1835
   1836	return 0;
   1837}
   1838
   1839/* Write a list of registers */
   1840static int imx319_write_regs(struct imx319 *imx319,
   1841			     const struct imx319_reg *regs, u32 len)
   1842{
   1843	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   1844	int ret;
   1845	u32 i;
   1846
   1847	for (i = 0; i < len; i++) {
   1848		ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val);
   1849		if (ret) {
   1850			dev_err_ratelimited(&client->dev,
   1851					    "write reg 0x%4.4x return err %d",
   1852					    regs[i].address, ret);
   1853			return ret;
   1854		}
   1855	}
   1856
   1857	return 0;
   1858}
   1859
   1860/* Open sub-device */
   1861static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
   1862{
   1863	struct imx319 *imx319 = to_imx319(sd);
   1864	struct v4l2_mbus_framefmt *try_fmt =
   1865		v4l2_subdev_get_try_format(sd, fh->state, 0);
   1866
   1867	mutex_lock(&imx319->mutex);
   1868
   1869	/* Initialize try_fmt */
   1870	try_fmt->width = imx319->cur_mode->width;
   1871	try_fmt->height = imx319->cur_mode->height;
   1872	try_fmt->code = imx319_get_format_code(imx319);
   1873	try_fmt->field = V4L2_FIELD_NONE;
   1874
   1875	mutex_unlock(&imx319->mutex);
   1876
   1877	return 0;
   1878}
   1879
   1880static int imx319_set_ctrl(struct v4l2_ctrl *ctrl)
   1881{
   1882	struct imx319 *imx319 = container_of(ctrl->handler,
   1883					     struct imx319, ctrl_handler);
   1884	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   1885	s64 max;
   1886	int ret;
   1887
   1888	/* Propagate change of current control to all related controls */
   1889	switch (ctrl->id) {
   1890	case V4L2_CID_VBLANK:
   1891		/* Update max exposure while meeting expected vblanking */
   1892		max = imx319->cur_mode->height + ctrl->val - 18;
   1893		__v4l2_ctrl_modify_range(imx319->exposure,
   1894					 imx319->exposure->minimum,
   1895					 max, imx319->exposure->step, max);
   1896		break;
   1897	}
   1898
   1899	/*
   1900	 * Applying V4L2 control value only happens
   1901	 * when power is up for streaming
   1902	 */
   1903	if (!pm_runtime_get_if_in_use(&client->dev))
   1904		return 0;
   1905
   1906	switch (ctrl->id) {
   1907	case V4L2_CID_ANALOGUE_GAIN:
   1908		/* Analog gain = 1024/(1024 - ctrl->val) times */
   1909		ret = imx319_write_reg(imx319, IMX319_REG_ANALOG_GAIN, 2,
   1910				       ctrl->val);
   1911		break;
   1912	case V4L2_CID_DIGITAL_GAIN:
   1913		ret = imx319_write_reg(imx319, IMX319_REG_DIG_GAIN_GLOBAL, 2,
   1914				       ctrl->val);
   1915		break;
   1916	case V4L2_CID_EXPOSURE:
   1917		ret = imx319_write_reg(imx319, IMX319_REG_EXPOSURE, 2,
   1918				       ctrl->val);
   1919		break;
   1920	case V4L2_CID_VBLANK:
   1921		/* Update FLL that meets expected vertical blanking */
   1922		ret = imx319_write_reg(imx319, IMX319_REG_FLL, 2,
   1923				       imx319->cur_mode->height + ctrl->val);
   1924		break;
   1925	case V4L2_CID_TEST_PATTERN:
   1926		ret = imx319_write_reg(imx319, IMX319_REG_TEST_PATTERN,
   1927				       2, ctrl->val);
   1928		break;
   1929	case V4L2_CID_HFLIP:
   1930	case V4L2_CID_VFLIP:
   1931		ret = imx319_write_reg(imx319, IMX319_REG_ORIENTATION, 1,
   1932				       imx319->hflip->val |
   1933				       imx319->vflip->val << 1);
   1934		break;
   1935	default:
   1936		ret = -EINVAL;
   1937		dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",
   1938			 ctrl->id, ctrl->val);
   1939		break;
   1940	}
   1941
   1942	pm_runtime_put(&client->dev);
   1943
   1944	return ret;
   1945}
   1946
   1947static const struct v4l2_ctrl_ops imx319_ctrl_ops = {
   1948	.s_ctrl = imx319_set_ctrl,
   1949};
   1950
   1951static int imx319_enum_mbus_code(struct v4l2_subdev *sd,
   1952				 struct v4l2_subdev_state *sd_state,
   1953				 struct v4l2_subdev_mbus_code_enum *code)
   1954{
   1955	struct imx319 *imx319 = to_imx319(sd);
   1956
   1957	if (code->index > 0)
   1958		return -EINVAL;
   1959
   1960	mutex_lock(&imx319->mutex);
   1961	code->code = imx319_get_format_code(imx319);
   1962	mutex_unlock(&imx319->mutex);
   1963
   1964	return 0;
   1965}
   1966
   1967static int imx319_enum_frame_size(struct v4l2_subdev *sd,
   1968				  struct v4l2_subdev_state *sd_state,
   1969				  struct v4l2_subdev_frame_size_enum *fse)
   1970{
   1971	struct imx319 *imx319 = to_imx319(sd);
   1972
   1973	if (fse->index >= ARRAY_SIZE(supported_modes))
   1974		return -EINVAL;
   1975
   1976	mutex_lock(&imx319->mutex);
   1977	if (fse->code != imx319_get_format_code(imx319)) {
   1978		mutex_unlock(&imx319->mutex);
   1979		return -EINVAL;
   1980	}
   1981	mutex_unlock(&imx319->mutex);
   1982
   1983	fse->min_width = supported_modes[fse->index].width;
   1984	fse->max_width = fse->min_width;
   1985	fse->min_height = supported_modes[fse->index].height;
   1986	fse->max_height = fse->min_height;
   1987
   1988	return 0;
   1989}
   1990
   1991static void imx319_update_pad_format(struct imx319 *imx319,
   1992				     const struct imx319_mode *mode,
   1993				     struct v4l2_subdev_format *fmt)
   1994{
   1995	fmt->format.width = mode->width;
   1996	fmt->format.height = mode->height;
   1997	fmt->format.code = imx319_get_format_code(imx319);
   1998	fmt->format.field = V4L2_FIELD_NONE;
   1999}
   2000
   2001static int imx319_do_get_pad_format(struct imx319 *imx319,
   2002				    struct v4l2_subdev_state *sd_state,
   2003				    struct v4l2_subdev_format *fmt)
   2004{
   2005	struct v4l2_mbus_framefmt *framefmt;
   2006	struct v4l2_subdev *sd = &imx319->sd;
   2007
   2008	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
   2009		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
   2010		fmt->format = *framefmt;
   2011	} else {
   2012		imx319_update_pad_format(imx319, imx319->cur_mode, fmt);
   2013	}
   2014
   2015	return 0;
   2016}
   2017
   2018static int imx319_get_pad_format(struct v4l2_subdev *sd,
   2019				 struct v4l2_subdev_state *sd_state,
   2020				 struct v4l2_subdev_format *fmt)
   2021{
   2022	struct imx319 *imx319 = to_imx319(sd);
   2023	int ret;
   2024
   2025	mutex_lock(&imx319->mutex);
   2026	ret = imx319_do_get_pad_format(imx319, sd_state, fmt);
   2027	mutex_unlock(&imx319->mutex);
   2028
   2029	return ret;
   2030}
   2031
   2032static int
   2033imx319_set_pad_format(struct v4l2_subdev *sd,
   2034		      struct v4l2_subdev_state *sd_state,
   2035		      struct v4l2_subdev_format *fmt)
   2036{
   2037	struct imx319 *imx319 = to_imx319(sd);
   2038	const struct imx319_mode *mode;
   2039	struct v4l2_mbus_framefmt *framefmt;
   2040	s32 vblank_def;
   2041	s32 vblank_min;
   2042	s64 h_blank;
   2043	u64 pixel_rate;
   2044	u32 height;
   2045
   2046	mutex_lock(&imx319->mutex);
   2047
   2048	/*
   2049	 * Only one bayer order is supported.
   2050	 * It depends on the flip settings.
   2051	 */
   2052	fmt->format.code = imx319_get_format_code(imx319);
   2053
   2054	mode = v4l2_find_nearest_size(supported_modes,
   2055				      ARRAY_SIZE(supported_modes),
   2056				      width, height,
   2057				      fmt->format.width, fmt->format.height);
   2058	imx319_update_pad_format(imx319, mode, fmt);
   2059	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
   2060		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
   2061		*framefmt = fmt->format;
   2062	} else {
   2063		imx319->cur_mode = mode;
   2064		pixel_rate = imx319->link_def_freq * 2 * 4;
   2065		do_div(pixel_rate, 10);
   2066		__v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate);
   2067		/* Update limits and set FPS to default */
   2068		height = imx319->cur_mode->height;
   2069		vblank_def = imx319->cur_mode->fll_def - height;
   2070		vblank_min = imx319->cur_mode->fll_min - height;
   2071		height = IMX319_FLL_MAX - height;
   2072		__v4l2_ctrl_modify_range(imx319->vblank, vblank_min, height, 1,
   2073					 vblank_def);
   2074		__v4l2_ctrl_s_ctrl(imx319->vblank, vblank_def);
   2075		h_blank = mode->llp - imx319->cur_mode->width;
   2076		/*
   2077		 * Currently hblank is not changeable.
   2078		 * So FPS control is done only by vblank.
   2079		 */
   2080		__v4l2_ctrl_modify_range(imx319->hblank, h_blank,
   2081					 h_blank, 1, h_blank);
   2082	}
   2083
   2084	mutex_unlock(&imx319->mutex);
   2085
   2086	return 0;
   2087}
   2088
   2089/* Verify chip ID */
   2090static int imx319_identify_module(struct imx319 *imx319)
   2091{
   2092	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   2093	int ret;
   2094	u32 val;
   2095
   2096	if (imx319->identified)
   2097		return 0;
   2098
   2099	ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
   2100	if (ret)
   2101		return ret;
   2102
   2103	if (val != IMX319_CHIP_ID) {
   2104		dev_err(&client->dev, "chip id mismatch: %x!=%x",
   2105			IMX319_CHIP_ID, val);
   2106		return -EIO;
   2107	}
   2108
   2109	imx319->identified = true;
   2110
   2111	return 0;
   2112}
   2113
   2114/* Start streaming */
   2115static int imx319_start_streaming(struct imx319 *imx319)
   2116{
   2117	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   2118	const struct imx319_reg_list *reg_list;
   2119	int ret;
   2120
   2121	ret = imx319_identify_module(imx319);
   2122	if (ret)
   2123		return ret;
   2124
   2125	/* Global Setting */
   2126	reg_list = &imx319_global_setting;
   2127	ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
   2128	if (ret) {
   2129		dev_err(&client->dev, "failed to set global settings");
   2130		return ret;
   2131	}
   2132
   2133	/* Apply default values of current mode */
   2134	reg_list = &imx319->cur_mode->reg_list;
   2135	ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
   2136	if (ret) {
   2137		dev_err(&client->dev, "failed to set mode");
   2138		return ret;
   2139	}
   2140
   2141	/* set digital gain control to all color mode */
   2142	ret = imx319_write_reg(imx319, IMX319_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
   2143	if (ret)
   2144		return ret;
   2145
   2146	/* Apply customized values from user */
   2147	ret =  __v4l2_ctrl_handler_setup(imx319->sd.ctrl_handler);
   2148	if (ret)
   2149		return ret;
   2150
   2151	return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
   2152				1, IMX319_MODE_STREAMING);
   2153}
   2154
   2155/* Stop streaming */
   2156static int imx319_stop_streaming(struct imx319 *imx319)
   2157{
   2158	return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
   2159				1, IMX319_MODE_STANDBY);
   2160}
   2161
   2162static int imx319_set_stream(struct v4l2_subdev *sd, int enable)
   2163{
   2164	struct imx319 *imx319 = to_imx319(sd);
   2165	struct i2c_client *client = v4l2_get_subdevdata(sd);
   2166	int ret = 0;
   2167
   2168	mutex_lock(&imx319->mutex);
   2169	if (imx319->streaming == enable) {
   2170		mutex_unlock(&imx319->mutex);
   2171		return 0;
   2172	}
   2173
   2174	if (enable) {
   2175		ret = pm_runtime_resume_and_get(&client->dev);
   2176		if (ret < 0)
   2177			goto err_unlock;
   2178
   2179		/*
   2180		 * Apply default & customized values
   2181		 * and then start streaming.
   2182		 */
   2183		ret = imx319_start_streaming(imx319);
   2184		if (ret)
   2185			goto err_rpm_put;
   2186	} else {
   2187		imx319_stop_streaming(imx319);
   2188		pm_runtime_put(&client->dev);
   2189	}
   2190
   2191	imx319->streaming = enable;
   2192
   2193	/* vflip and hflip cannot change during streaming */
   2194	__v4l2_ctrl_grab(imx319->vflip, enable);
   2195	__v4l2_ctrl_grab(imx319->hflip, enable);
   2196
   2197	mutex_unlock(&imx319->mutex);
   2198
   2199	return ret;
   2200
   2201err_rpm_put:
   2202	pm_runtime_put(&client->dev);
   2203err_unlock:
   2204	mutex_unlock(&imx319->mutex);
   2205
   2206	return ret;
   2207}
   2208
   2209static int __maybe_unused imx319_suspend(struct device *dev)
   2210{
   2211	struct v4l2_subdev *sd = dev_get_drvdata(dev);
   2212	struct imx319 *imx319 = to_imx319(sd);
   2213
   2214	if (imx319->streaming)
   2215		imx319_stop_streaming(imx319);
   2216
   2217	return 0;
   2218}
   2219
   2220static int __maybe_unused imx319_resume(struct device *dev)
   2221{
   2222	struct v4l2_subdev *sd = dev_get_drvdata(dev);
   2223	struct imx319 *imx319 = to_imx319(sd);
   2224	int ret;
   2225
   2226	if (imx319->streaming) {
   2227		ret = imx319_start_streaming(imx319);
   2228		if (ret)
   2229			goto error;
   2230	}
   2231
   2232	return 0;
   2233
   2234error:
   2235	imx319_stop_streaming(imx319);
   2236	imx319->streaming = 0;
   2237	return ret;
   2238}
   2239
   2240static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {
   2241	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
   2242	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
   2243};
   2244
   2245static const struct v4l2_subdev_video_ops imx319_video_ops = {
   2246	.s_stream = imx319_set_stream,
   2247};
   2248
   2249static const struct v4l2_subdev_pad_ops imx319_pad_ops = {
   2250	.enum_mbus_code = imx319_enum_mbus_code,
   2251	.get_fmt = imx319_get_pad_format,
   2252	.set_fmt = imx319_set_pad_format,
   2253	.enum_frame_size = imx319_enum_frame_size,
   2254};
   2255
   2256static const struct v4l2_subdev_ops imx319_subdev_ops = {
   2257	.core = &imx319_subdev_core_ops,
   2258	.video = &imx319_video_ops,
   2259	.pad = &imx319_pad_ops,
   2260};
   2261
   2262static const struct media_entity_operations imx319_subdev_entity_ops = {
   2263	.link_validate = v4l2_subdev_link_validate,
   2264};
   2265
   2266static const struct v4l2_subdev_internal_ops imx319_internal_ops = {
   2267	.open = imx319_open,
   2268};
   2269
   2270/* Initialize control handlers */
   2271static int imx319_init_controls(struct imx319 *imx319)
   2272{
   2273	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
   2274	struct v4l2_ctrl_handler *ctrl_hdlr;
   2275	s64 exposure_max;
   2276	s64 vblank_def;
   2277	s64 vblank_min;
   2278	s64 hblank;
   2279	u64 pixel_rate;
   2280	const struct imx319_mode *mode;
   2281	u32 max;
   2282	int ret;
   2283
   2284	ctrl_hdlr = &imx319->ctrl_handler;
   2285	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
   2286	if (ret)
   2287		return ret;
   2288
   2289	ctrl_hdlr->lock = &imx319->mutex;
   2290	max = ARRAY_SIZE(link_freq_menu_items) - 1;
   2291	imx319->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx319_ctrl_ops,
   2292						   V4L2_CID_LINK_FREQ, max, 0,
   2293						   link_freq_menu_items);
   2294	if (imx319->link_freq)
   2295		imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
   2296
   2297	/* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
   2298	pixel_rate = imx319->link_def_freq * 2 * 4;
   2299	do_div(pixel_rate, 10);
   2300	/* By default, PIXEL_RATE is read only */
   2301	imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2302					       V4L2_CID_PIXEL_RATE, pixel_rate,
   2303					       pixel_rate, 1, pixel_rate);
   2304
   2305	/* Initial vblank/hblank/exposure parameters based on current mode */
   2306	mode = imx319->cur_mode;
   2307	vblank_def = mode->fll_def - mode->height;
   2308	vblank_min = mode->fll_min - mode->height;
   2309	imx319->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2310					   V4L2_CID_VBLANK, vblank_min,
   2311					   IMX319_FLL_MAX - mode->height,
   2312					   1, vblank_def);
   2313
   2314	hblank = mode->llp - mode->width;
   2315	imx319->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2316					   V4L2_CID_HBLANK, hblank, hblank,
   2317					   1, hblank);
   2318	if (imx319->hblank)
   2319		imx319->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
   2320
   2321	/* fll >= exposure time + adjust parameter (default value is 18) */
   2322	exposure_max = mode->fll_def - 18;
   2323	imx319->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2324					     V4L2_CID_EXPOSURE,
   2325					     IMX319_EXPOSURE_MIN, exposure_max,
   2326					     IMX319_EXPOSURE_STEP,
   2327					     IMX319_EXPOSURE_DEFAULT);
   2328
   2329	imx319->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2330					  V4L2_CID_HFLIP, 0, 1, 1, 0);
   2331	imx319->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
   2332					  V4L2_CID_VFLIP, 0, 1, 1, 0);
   2333
   2334	v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
   2335			  IMX319_ANA_GAIN_MIN, IMX319_ANA_GAIN_MAX,
   2336			  IMX319_ANA_GAIN_STEP, IMX319_ANA_GAIN_DEFAULT);
   2337
   2338	/* Digital gain */
   2339	v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
   2340			  IMX319_DGTL_GAIN_MIN, IMX319_DGTL_GAIN_MAX,
   2341			  IMX319_DGTL_GAIN_STEP, IMX319_DGTL_GAIN_DEFAULT);
   2342
   2343	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx319_ctrl_ops,
   2344				     V4L2_CID_TEST_PATTERN,
   2345				     ARRAY_SIZE(imx319_test_pattern_menu) - 1,
   2346				     0, 0, imx319_test_pattern_menu);
   2347	if (ctrl_hdlr->error) {
   2348		ret = ctrl_hdlr->error;
   2349		dev_err(&client->dev, "control init failed: %d", ret);
   2350		goto error;
   2351	}
   2352
   2353	imx319->sd.ctrl_handler = ctrl_hdlr;
   2354
   2355	return 0;
   2356
   2357error:
   2358	v4l2_ctrl_handler_free(ctrl_hdlr);
   2359
   2360	return ret;
   2361}
   2362
   2363static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)
   2364{
   2365	struct imx319_hwcfg *cfg;
   2366	struct v4l2_fwnode_endpoint bus_cfg = {
   2367		.bus_type = V4L2_MBUS_CSI2_DPHY
   2368	};
   2369	struct fwnode_handle *ep;
   2370	struct fwnode_handle *fwnode = dev_fwnode(dev);
   2371	unsigned int i;
   2372	int ret;
   2373
   2374	if (!fwnode)
   2375		return NULL;
   2376
   2377	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
   2378	if (!ep)
   2379		return NULL;
   2380
   2381	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
   2382	if (ret)
   2383		goto out_err;
   2384
   2385	cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
   2386	if (!cfg)
   2387		goto out_err;
   2388
   2389	ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
   2390				       &cfg->ext_clk);
   2391	if (ret) {
   2392		dev_err(dev, "can't get clock frequency");
   2393		goto out_err;
   2394	}
   2395
   2396	dev_dbg(dev, "ext clk: %d", cfg->ext_clk);
   2397	if (cfg->ext_clk != IMX319_EXT_CLK) {
   2398		dev_err(dev, "external clock %d is not supported",
   2399			cfg->ext_clk);
   2400		goto out_err;
   2401	}
   2402
   2403	dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies);
   2404	if (!bus_cfg.nr_of_link_frequencies) {
   2405		dev_warn(dev, "no link frequencies defined");
   2406		goto out_err;
   2407	}
   2408
   2409	cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies;
   2410	cfg->link_freqs = devm_kcalloc(dev,
   2411				       bus_cfg.nr_of_link_frequencies + 1,
   2412				       sizeof(*cfg->link_freqs), GFP_KERNEL);
   2413	if (!cfg->link_freqs)
   2414		goto out_err;
   2415
   2416	for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
   2417		cfg->link_freqs[i] = bus_cfg.link_frequencies[i];
   2418		dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]);
   2419	}
   2420
   2421	v4l2_fwnode_endpoint_free(&bus_cfg);
   2422	fwnode_handle_put(ep);
   2423	return cfg;
   2424
   2425out_err:
   2426	v4l2_fwnode_endpoint_free(&bus_cfg);
   2427	fwnode_handle_put(ep);
   2428	return NULL;
   2429}
   2430
   2431static int imx319_probe(struct i2c_client *client)
   2432{
   2433	struct imx319 *imx319;
   2434	bool full_power;
   2435	int ret;
   2436	u32 i;
   2437
   2438	imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL);
   2439	if (!imx319)
   2440		return -ENOMEM;
   2441
   2442	mutex_init(&imx319->mutex);
   2443
   2444	/* Initialize subdev */
   2445	v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);
   2446
   2447	full_power = acpi_dev_state_d0(&client->dev);
   2448	if (full_power) {
   2449		/* Check module identity */
   2450		ret = imx319_identify_module(imx319);
   2451		if (ret) {
   2452			dev_err(&client->dev, "failed to find sensor: %d", ret);
   2453			goto error_probe;
   2454		}
   2455	}
   2456
   2457	imx319->hwcfg = imx319_get_hwcfg(&client->dev);
   2458	if (!imx319->hwcfg) {
   2459		dev_err(&client->dev, "failed to get hwcfg");
   2460		ret = -ENODEV;
   2461		goto error_probe;
   2462	}
   2463
   2464	imx319->link_def_freq = link_freq_menu_items[IMX319_LINK_FREQ_INDEX];
   2465	for (i = 0; i < imx319->hwcfg->nr_of_link_freqs; i++) {
   2466		if (imx319->hwcfg->link_freqs[i] == imx319->link_def_freq) {
   2467			dev_dbg(&client->dev, "link freq index %d matched", i);
   2468			break;
   2469		}
   2470	}
   2471
   2472	if (i == imx319->hwcfg->nr_of_link_freqs) {
   2473		dev_err(&client->dev, "no link frequency supported");
   2474		ret = -EINVAL;
   2475		goto error_probe;
   2476	}
   2477
   2478	/* Set default mode to max resolution */
   2479	imx319->cur_mode = &supported_modes[0];
   2480
   2481	ret = imx319_init_controls(imx319);
   2482	if (ret) {
   2483		dev_err(&client->dev, "failed to init controls: %d", ret);
   2484		goto error_probe;
   2485	}
   2486
   2487	/* Initialize subdev */
   2488	imx319->sd.internal_ops = &imx319_internal_ops;
   2489	imx319->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
   2490		V4L2_SUBDEV_FL_HAS_EVENTS;
   2491	imx319->sd.entity.ops = &imx319_subdev_entity_ops;
   2492	imx319->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
   2493
   2494	/* Initialize source pad */
   2495	imx319->pad.flags = MEDIA_PAD_FL_SOURCE;
   2496	ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad);
   2497	if (ret) {
   2498		dev_err(&client->dev, "failed to init entity pads: %d", ret);
   2499		goto error_handler_free;
   2500	}
   2501
   2502	ret = v4l2_async_register_subdev_sensor(&imx319->sd);
   2503	if (ret < 0)
   2504		goto error_media_entity;
   2505
   2506	/* Set the device's state to active if it's in D0 state. */
   2507	if (full_power)
   2508		pm_runtime_set_active(&client->dev);
   2509	pm_runtime_enable(&client->dev);
   2510	pm_runtime_idle(&client->dev);
   2511
   2512	return 0;
   2513
   2514error_media_entity:
   2515	media_entity_cleanup(&imx319->sd.entity);
   2516
   2517error_handler_free:
   2518	v4l2_ctrl_handler_free(imx319->sd.ctrl_handler);
   2519
   2520error_probe:
   2521	mutex_destroy(&imx319->mutex);
   2522
   2523	return ret;
   2524}
   2525
   2526static int imx319_remove(struct i2c_client *client)
   2527{
   2528	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   2529	struct imx319 *imx319 = to_imx319(sd);
   2530
   2531	v4l2_async_unregister_subdev(sd);
   2532	media_entity_cleanup(&sd->entity);
   2533	v4l2_ctrl_handler_free(sd->ctrl_handler);
   2534
   2535	pm_runtime_disable(&client->dev);
   2536	pm_runtime_set_suspended(&client->dev);
   2537
   2538	mutex_destroy(&imx319->mutex);
   2539
   2540	return 0;
   2541}
   2542
   2543static const struct dev_pm_ops imx319_pm_ops = {
   2544	SET_SYSTEM_SLEEP_PM_OPS(imx319_suspend, imx319_resume)
   2545};
   2546
   2547static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = {
   2548	{ "SONY319A" },
   2549	{ /* sentinel */ }
   2550};
   2551MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids);
   2552
   2553static struct i2c_driver imx319_i2c_driver = {
   2554	.driver = {
   2555		.name = "imx319",
   2556		.pm = &imx319_pm_ops,
   2557		.acpi_match_table = ACPI_PTR(imx319_acpi_ids),
   2558	},
   2559	.probe_new = imx319_probe,
   2560	.remove = imx319_remove,
   2561	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
   2562};
   2563module_i2c_driver(imx319_i2c_driver);
   2564
   2565MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
   2566MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
   2567MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
   2568MODULE_AUTHOR("Yang, Hyungwoo");
   2569MODULE_DESCRIPTION("Sony imx319 sensor driver");
   2570MODULE_LICENSE("GPL v2");