File Index
Files and directories
Sign in
FILE

imx319.c

File preview with syntax highlighting.

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