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