1/*
2 * Driver for OV5642 CMOS Image Sensor from Omnivision
3 *
4 * Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
5 *
6 * Based on Sony IMX074 Camera Driver
7 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
8 *
9 * Based on Omnivision OV7670 Camera Driver
10 * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/bitops.h>
18#include <linux/delay.h>
19#include <linux/i2c.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/videodev2.h>
23#include <linux/module.h>
24#include <linux/v4l2-mediabus.h>
25
26#include <media/soc_camera.h>
27#include <media/v4l2-clk.h>
28#include <media/v4l2-subdev.h>
29
30/* OV5642 registers */
31#define REG_CHIP_ID_HIGH		0x300a
32#define REG_CHIP_ID_LOW			0x300b
33
34#define REG_WINDOW_START_X_HIGH		0x3800
35#define REG_WINDOW_START_X_LOW		0x3801
36#define REG_WINDOW_START_Y_HIGH		0x3802
37#define REG_WINDOW_START_Y_LOW		0x3803
38#define REG_WINDOW_WIDTH_HIGH		0x3804
39#define REG_WINDOW_WIDTH_LOW		0x3805
40#define REG_WINDOW_HEIGHT_HIGH		0x3806
41#define REG_WINDOW_HEIGHT_LOW		0x3807
42#define REG_OUT_WIDTH_HIGH		0x3808
43#define REG_OUT_WIDTH_LOW		0x3809
44#define REG_OUT_HEIGHT_HIGH		0x380a
45#define REG_OUT_HEIGHT_LOW		0x380b
46#define REG_OUT_TOTAL_WIDTH_HIGH	0x380c
47#define REG_OUT_TOTAL_WIDTH_LOW		0x380d
48#define REG_OUT_TOTAL_HEIGHT_HIGH	0x380e
49#define REG_OUT_TOTAL_HEIGHT_LOW	0x380f
50#define REG_OUTPUT_FORMAT		0x4300
51#define REG_ISP_CTRL_01			0x5001
52#define REG_AVG_WINDOW_END_X_HIGH	0x5682
53#define REG_AVG_WINDOW_END_X_LOW	0x5683
54#define REG_AVG_WINDOW_END_Y_HIGH	0x5686
55#define REG_AVG_WINDOW_END_Y_LOW	0x5687
56
57/* active pixel array size */
58#define OV5642_SENSOR_SIZE_X	2592
59#define OV5642_SENSOR_SIZE_Y	1944
60
61/*
62 * About OV5642 resolution, cropping and binning:
63 * This sensor supports it all, at least in the feature description.
64 * Unfortunately, no combination of appropriate registers settings could make
65 * the chip work the intended way. As it works with predefined register lists,
66 * some undocumented registers are presumably changed there to achieve their
67 * goals.
68 * This driver currently only works for resolutions up to 720 lines with a
69 * 1:1 scale. Hopefully these restrictions will be removed in the future.
70 */
71#define OV5642_MAX_WIDTH	OV5642_SENSOR_SIZE_X
72#define OV5642_MAX_HEIGHT	720
73
74/* default sizes */
75#define OV5642_DEFAULT_WIDTH	1280
76#define OV5642_DEFAULT_HEIGHT	OV5642_MAX_HEIGHT
77
78/* minimum extra blanking */
79#define BLANKING_EXTRA_WIDTH		500
80#define BLANKING_EXTRA_HEIGHT		20
81
82/*
83 * the sensor's autoexposure is buggy when setting total_height low.
84 * It tries to expose longer than 1 frame period without taking care of it
85 * and this leads to weird output. So we set 1000 lines as minimum.
86 */
87#define BLANKING_MIN_HEIGHT		1000
88
89struct regval_list {
90	u16 reg_num;
91	u8 value;
92};
93
94static struct regval_list ov5642_default_regs_init[] = {
95	{ 0x3103, 0x93 },
96	{ 0x3008, 0x82 },
97	{ 0x3017, 0x7f },
98	{ 0x3018, 0xfc },
99	{ 0x3810, 0xc2 },
100	{ 0x3615, 0xf0 },
101	{ 0x3000, 0x0  },
102	{ 0x3001, 0x0  },
103	{ 0x3002, 0x0  },
104	{ 0x3003, 0x0  },
105	{ 0x3004, 0xff },
106	{ 0x3030, 0x2b },
107	{ 0x3011, 0x8  },
108	{ 0x3010, 0x10 },
109	{ 0x3604, 0x60 },
110	{ 0x3622, 0x60 },
111	{ 0x3621, 0x9  },
112	{ 0x3709, 0x0  },
113	{ 0x4000, 0x21 },
114	{ 0x401d, 0x22 },
115	{ 0x3600, 0x54 },
116	{ 0x3605, 0x4  },
117	{ 0x3606, 0x3f },
118	{ 0x3c01, 0x80 },
119	{ 0x300d, 0x22 },
120	{ 0x3623, 0x22 },
121	{ 0x5000, 0x4f },
122	{ 0x5020, 0x4  },
123	{ 0x5181, 0x79 },
124	{ 0x5182, 0x0  },
125	{ 0x5185, 0x22 },
126	{ 0x5197, 0x1  },
127	{ 0x5500, 0xa  },
128	{ 0x5504, 0x0  },
129	{ 0x5505, 0x7f },
130	{ 0x5080, 0x8  },
131	{ 0x300e, 0x18 },
132	{ 0x4610, 0x0  },
133	{ 0x471d, 0x5  },
134	{ 0x4708, 0x6  },
135	{ 0x370c, 0xa0 },
136	{ 0x5687, 0x94 },
137	{ 0x501f, 0x0  },
138	{ 0x5000, 0x4f },
139	{ 0x5001, 0xcf },
140	{ 0x4300, 0x30 },
141	{ 0x4300, 0x30 },
142	{ 0x460b, 0x35 },
143	{ 0x471d, 0x0  },
144	{ 0x3002, 0xc  },
145	{ 0x3002, 0x0  },
146	{ 0x4713, 0x3  },
147	{ 0x471c, 0x50 },
148	{ 0x4721, 0x2  },
149	{ 0x4402, 0x90 },
150	{ 0x460c, 0x22 },
151	{ 0x3815, 0x44 },
152	{ 0x3503, 0x7  },
153	{ 0x3501, 0x73 },
154	{ 0x3502, 0x80 },
155	{ 0x350b, 0x0  },
156	{ 0x3818, 0xc8 },
157	{ 0x3824, 0x11 },
158	{ 0x3a00, 0x78 },
159	{ 0x3a1a, 0x4  },
160	{ 0x3a13, 0x30 },
161	{ 0x3a18, 0x0  },
162	{ 0x3a19, 0x7c },
163	{ 0x3a08, 0x12 },
164	{ 0x3a09, 0xc0 },
165	{ 0x3a0a, 0xf  },
166	{ 0x3a0b, 0xa0 },
167	{ 0x350c, 0x7  },
168	{ 0x350d, 0xd0 },
169	{ 0x3a0d, 0x8  },
170	{ 0x3a0e, 0x6  },
171	{ 0x3500, 0x0  },
172	{ 0x3501, 0x0  },
173	{ 0x3502, 0x0  },
174	{ 0x350a, 0x0  },
175	{ 0x350b, 0x0  },
176	{ 0x3503, 0x0  },
177	{ 0x3a0f, 0x3c },
178	{ 0x3a10, 0x32 },
179	{ 0x3a1b, 0x3c },
180	{ 0x3a1e, 0x32 },
181	{ 0x3a11, 0x80 },
182	{ 0x3a1f, 0x20 },
183	{ 0x3030, 0x2b },
184	{ 0x3a02, 0x0  },
185	{ 0x3a03, 0x7d },
186	{ 0x3a04, 0x0  },
187	{ 0x3a14, 0x0  },
188	{ 0x3a15, 0x7d },
189	{ 0x3a16, 0x0  },
190	{ 0x3a00, 0x78 },
191	{ 0x3a08, 0x9  },
192	{ 0x3a09, 0x60 },
193	{ 0x3a0a, 0x7  },
194	{ 0x3a0b, 0xd0 },
195	{ 0x3a0d, 0x10 },
196	{ 0x3a0e, 0xd  },
197	{ 0x4407, 0x4  },
198	{ 0x5193, 0x70 },
199	{ 0x589b, 0x0  },
200	{ 0x589a, 0xc0 },
201	{ 0x401e, 0x20 },
202	{ 0x4001, 0x42 },
203	{ 0x401c, 0x6  },
204	{ 0x3825, 0xac },
205	{ 0x3827, 0xc  },
206	{ 0x528a, 0x1  },
207	{ 0x528b, 0x4  },
208	{ 0x528c, 0x8  },
209	{ 0x528d, 0x10 },
210	{ 0x528e, 0x20 },
211	{ 0x528f, 0x28 },
212	{ 0x5290, 0x30 },
213	{ 0x5292, 0x0  },
214	{ 0x5293, 0x1  },
215	{ 0x5294, 0x0  },
216	{ 0x5295, 0x4  },
217	{ 0x5296, 0x0  },
218	{ 0x5297, 0x8  },
219	{ 0x5298, 0x0  },
220	{ 0x5299, 0x10 },
221	{ 0x529a, 0x0  },
222	{ 0x529b, 0x20 },
223	{ 0x529c, 0x0  },
224	{ 0x529d, 0x28 },
225	{ 0x529e, 0x0  },
226	{ 0x529f, 0x30 },
227	{ 0x5282, 0x0  },
228	{ 0x5300, 0x0  },
229	{ 0x5301, 0x20 },
230	{ 0x5302, 0x0  },
231	{ 0x5303, 0x7c },
232	{ 0x530c, 0x0  },
233	{ 0x530d, 0xc  },
234	{ 0x530e, 0x20 },
235	{ 0x530f, 0x80 },
236	{ 0x5310, 0x20 },
237	{ 0x5311, 0x80 },
238	{ 0x5308, 0x20 },
239	{ 0x5309, 0x40 },
240	{ 0x5304, 0x0  },
241	{ 0x5305, 0x30 },
242	{ 0x5306, 0x0  },
243	{ 0x5307, 0x80 },
244	{ 0x5314, 0x8  },
245	{ 0x5315, 0x20 },
246	{ 0x5319, 0x30 },
247	{ 0x5316, 0x10 },
248	{ 0x5317, 0x0  },
249	{ 0x5318, 0x2  },
250	{ 0x5380, 0x1  },
251	{ 0x5381, 0x0  },
252	{ 0x5382, 0x0  },
253	{ 0x5383, 0x4e },
254	{ 0x5384, 0x0  },
255	{ 0x5385, 0xf  },
256	{ 0x5386, 0x0  },
257	{ 0x5387, 0x0  },
258	{ 0x5388, 0x1  },
259	{ 0x5389, 0x15 },
260	{ 0x538a, 0x0  },
261	{ 0x538b, 0x31 },
262	{ 0x538c, 0x0  },
263	{ 0x538d, 0x0  },
264	{ 0x538e, 0x0  },
265	{ 0x538f, 0xf  },
266	{ 0x5390, 0x0  },
267	{ 0x5391, 0xab },
268	{ 0x5392, 0x0  },
269	{ 0x5393, 0xa2 },
270	{ 0x5394, 0x8  },
271	{ 0x5480, 0x14 },
272	{ 0x5481, 0x21 },
273	{ 0x5482, 0x36 },
274	{ 0x5483, 0x57 },
275	{ 0x5484, 0x65 },
276	{ 0x5485, 0x71 },
277	{ 0x5486, 0x7d },
278	{ 0x5487, 0x87 },
279	{ 0x5488, 0x91 },
280	{ 0x5489, 0x9a },
281	{ 0x548a, 0xaa },
282	{ 0x548b, 0xb8 },
283	{ 0x548c, 0xcd },
284	{ 0x548d, 0xdd },
285	{ 0x548e, 0xea },
286	{ 0x548f, 0x1d },
287	{ 0x5490, 0x5  },
288	{ 0x5491, 0x0  },
289	{ 0x5492, 0x4  },
290	{ 0x5493, 0x20 },
291	{ 0x5494, 0x3  },
292	{ 0x5495, 0x60 },
293	{ 0x5496, 0x2  },
294	{ 0x5497, 0xb8 },
295	{ 0x5498, 0x2  },
296	{ 0x5499, 0x86 },
297	{ 0x549a, 0x2  },
298	{ 0x549b, 0x5b },
299	{ 0x549c, 0x2  },
300	{ 0x549d, 0x3b },
301	{ 0x549e, 0x2  },
302	{ 0x549f, 0x1c },
303	{ 0x54a0, 0x2  },
304	{ 0x54a1, 0x4  },
305	{ 0x54a2, 0x1  },
306	{ 0x54a3, 0xed },
307	{ 0x54a4, 0x1  },
308	{ 0x54a5, 0xc5 },
309	{ 0x54a6, 0x1  },
310	{ 0x54a7, 0xa5 },
311	{ 0x54a8, 0x1  },
312	{ 0x54a9, 0x6c },
313	{ 0x54aa, 0x1  },
314	{ 0x54ab, 0x41 },
315	{ 0x54ac, 0x1  },
316	{ 0x54ad, 0x20 },
317	{ 0x54ae, 0x0  },
318	{ 0x54af, 0x16 },
319	{ 0x54b0, 0x1  },
320	{ 0x54b1, 0x20 },
321	{ 0x54b2, 0x0  },
322	{ 0x54b3, 0x10 },
323	{ 0x54b4, 0x0  },
324	{ 0x54b5, 0xf0 },
325	{ 0x54b6, 0x0  },
326	{ 0x54b7, 0xdf },
327	{ 0x5402, 0x3f },
328	{ 0x5403, 0x0  },
329	{ 0x3406, 0x0  },
330	{ 0x5180, 0xff },
331	{ 0x5181, 0x52 },
332	{ 0x5182, 0x11 },
333	{ 0x5183, 0x14 },
334	{ 0x5184, 0x25 },
335	{ 0x5185, 0x24 },
336	{ 0x5186, 0x6  },
337	{ 0x5187, 0x8  },
338	{ 0x5188, 0x8  },
339	{ 0x5189, 0x7c },
340	{ 0x518a, 0x60 },
341	{ 0x518b, 0xb2 },
342	{ 0x518c, 0xb2 },
343	{ 0x518d, 0x44 },
344	{ 0x518e, 0x3d },
345	{ 0x518f, 0x58 },
346	{ 0x5190, 0x46 },
347	{ 0x5191, 0xf8 },
348	{ 0x5192, 0x4  },
349	{ 0x5193, 0x70 },
350	{ 0x5194, 0xf0 },
351	{ 0x5195, 0xf0 },
352	{ 0x5196, 0x3  },
353	{ 0x5197, 0x1  },
354	{ 0x5198, 0x4  },
355	{ 0x5199, 0x12 },
356	{ 0x519a, 0x4  },
357	{ 0x519b, 0x0  },
358	{ 0x519c, 0x6  },
359	{ 0x519d, 0x82 },
360	{ 0x519e, 0x0  },
361	{ 0x5025, 0x80 },
362	{ 0x3a0f, 0x38 },
363	{ 0x3a10, 0x30 },
364	{ 0x3a1b, 0x3a },
365	{ 0x3a1e, 0x2e },
366	{ 0x3a11, 0x60 },
367	{ 0x3a1f, 0x10 },
368	{ 0x5688, 0xa6 },
369	{ 0x5689, 0x6a },
370	{ 0x568a, 0xea },
371	{ 0x568b, 0xae },
372	{ 0x568c, 0xa6 },
373	{ 0x568d, 0x6a },
374	{ 0x568e, 0x62 },
375	{ 0x568f, 0x26 },
376	{ 0x5583, 0x40 },
377	{ 0x5584, 0x40 },
378	{ 0x5580, 0x2  },
379	{ 0x5000, 0xcf },
380	{ 0x5800, 0x27 },
381	{ 0x5801, 0x19 },
382	{ 0x5802, 0x12 },
383	{ 0x5803, 0xf  },
384	{ 0x5804, 0x10 },
385	{ 0x5805, 0x15 },
386	{ 0x5806, 0x1e },
387	{ 0x5807, 0x2f },
388	{ 0x5808, 0x15 },
389	{ 0x5809, 0xd  },
390	{ 0x580a, 0xa  },
391	{ 0x580b, 0x9  },
392	{ 0x580c, 0xa  },
393	{ 0x580d, 0xc  },
394	{ 0x580e, 0x12 },
395	{ 0x580f, 0x19 },
396	{ 0x5810, 0xb  },
397	{ 0x5811, 0x7  },
398	{ 0x5812, 0x4  },
399	{ 0x5813, 0x3  },
400	{ 0x5814, 0x3  },
401	{ 0x5815, 0x6  },
402	{ 0x5816, 0xa  },
403	{ 0x5817, 0xf  },
404	{ 0x5818, 0xa  },
405	{ 0x5819, 0x5  },
406	{ 0x581a, 0x1  },
407	{ 0x581b, 0x0  },
408	{ 0x581c, 0x0  },
409	{ 0x581d, 0x3  },
410	{ 0x581e, 0x8  },
411	{ 0x581f, 0xc  },
412	{ 0x5820, 0xa  },
413	{ 0x5821, 0x5  },
414	{ 0x5822, 0x1  },
415	{ 0x5823, 0x0  },
416	{ 0x5824, 0x0  },
417	{ 0x5825, 0x3  },
418	{ 0x5826, 0x8  },
419	{ 0x5827, 0xc  },
420	{ 0x5828, 0xe  },
421	{ 0x5829, 0x8  },
422	{ 0x582a, 0x6  },
423	{ 0x582b, 0x4  },
424	{ 0x582c, 0x5  },
425	{ 0x582d, 0x7  },
426	{ 0x582e, 0xb  },
427	{ 0x582f, 0x12 },
428	{ 0x5830, 0x18 },
429	{ 0x5831, 0x10 },
430	{ 0x5832, 0xc  },
431	{ 0x5833, 0xa  },
432	{ 0x5834, 0xb  },
433	{ 0x5835, 0xe  },
434	{ 0x5836, 0x15 },
435	{ 0x5837, 0x19 },
436	{ 0x5838, 0x32 },
437	{ 0x5839, 0x1f },
438	{ 0x583a, 0x18 },
439	{ 0x583b, 0x16 },
440	{ 0x583c, 0x17 },
441	{ 0x583d, 0x1e },
442	{ 0x583e, 0x26 },
443	{ 0x583f, 0x53 },
444	{ 0x5840, 0x10 },
445	{ 0x5841, 0xf  },
446	{ 0x5842, 0xd  },
447	{ 0x5843, 0xc  },
448	{ 0x5844, 0xe  },
449	{ 0x5845, 0x9  },
450	{ 0x5846, 0x11 },
451	{ 0x5847, 0x10 },
452	{ 0x5848, 0x10 },
453	{ 0x5849, 0x10 },
454	{ 0x584a, 0x10 },
455	{ 0x584b, 0xe  },
456	{ 0x584c, 0x10 },
457	{ 0x584d, 0x10 },
458	{ 0x584e, 0x11 },
459	{ 0x584f, 0x10 },
460	{ 0x5850, 0xf  },
461	{ 0x5851, 0xc  },
462	{ 0x5852, 0xf  },
463	{ 0x5853, 0x10 },
464	{ 0x5854, 0x10 },
465	{ 0x5855, 0xf  },
466	{ 0x5856, 0xe  },
467	{ 0x5857, 0xb  },
468	{ 0x5858, 0x10 },
469	{ 0x5859, 0xd  },
470	{ 0x585a, 0xd  },
471	{ 0x585b, 0xc  },
472	{ 0x585c, 0xc  },
473	{ 0x585d, 0xc  },
474	{ 0x585e, 0xb  },
475	{ 0x585f, 0xc  },
476	{ 0x5860, 0xc  },
477	{ 0x5861, 0xc  },
478	{ 0x5862, 0xd  },
479	{ 0x5863, 0x8  },
480	{ 0x5864, 0x11 },
481	{ 0x5865, 0x18 },
482	{ 0x5866, 0x18 },
483	{ 0x5867, 0x19 },
484	{ 0x5868, 0x17 },
485	{ 0x5869, 0x19 },
486	{ 0x586a, 0x16 },
487	{ 0x586b, 0x13 },
488	{ 0x586c, 0x13 },
489	{ 0x586d, 0x12 },
490	{ 0x586e, 0x13 },
491	{ 0x586f, 0x16 },
492	{ 0x5870, 0x14 },
493	{ 0x5871, 0x12 },
494	{ 0x5872, 0x10 },
495	{ 0x5873, 0x11 },
496	{ 0x5874, 0x11 },
497	{ 0x5875, 0x16 },
498	{ 0x5876, 0x14 },
499	{ 0x5877, 0x11 },
500	{ 0x5878, 0x10 },
501	{ 0x5879, 0xf  },
502	{ 0x587a, 0x10 },
503	{ 0x587b, 0x14 },
504	{ 0x587c, 0x13 },
505	{ 0x587d, 0x12 },
506	{ 0x587e, 0x11 },
507	{ 0x587f, 0x11 },
508	{ 0x5880, 0x12 },
509	{ 0x5881, 0x15 },
510	{ 0x5882, 0x14 },
511	{ 0x5883, 0x15 },
512	{ 0x5884, 0x15 },
513	{ 0x5885, 0x15 },
514	{ 0x5886, 0x13 },
515	{ 0x5887, 0x17 },
516	{ 0x3710, 0x10 },
517	{ 0x3632, 0x51 },
518	{ 0x3702, 0x10 },
519	{ 0x3703, 0xb2 },
520	{ 0x3704, 0x18 },
521	{ 0x370b, 0x40 },
522	{ 0x370d, 0x3  },
523	{ 0x3631, 0x1  },
524	{ 0x3632, 0x52 },
525	{ 0x3606, 0x24 },
526	{ 0x3620, 0x96 },
527	{ 0x5785, 0x7  },
528	{ 0x3a13, 0x30 },
529	{ 0x3600, 0x52 },
530	{ 0x3604, 0x48 },
531	{ 0x3606, 0x1b },
532	{ 0x370d, 0xb  },
533	{ 0x370f, 0xc0 },
534	{ 0x3709, 0x1  },
535	{ 0x3823, 0x0  },
536	{ 0x5007, 0x0  },
537	{ 0x5009, 0x0  },
538	{ 0x5011, 0x0  },
539	{ 0x5013, 0x0  },
540	{ 0x519e, 0x0  },
541	{ 0x5086, 0x0  },
542	{ 0x5087, 0x0  },
543	{ 0x5088, 0x0  },
544	{ 0x5089, 0x0  },
545	{ 0x302b, 0x0  },
546	{ 0x3503, 0x7  },
547	{ 0x3011, 0x8  },
548	{ 0x350c, 0x2  },
549	{ 0x350d, 0xe4 },
550	{ 0x3621, 0xc9 },
551	{ 0x370a, 0x81 },
552	{ 0xffff, 0xff },
553};
554
555static struct regval_list ov5642_default_regs_finalise[] = {
556	{ 0x3810, 0xc2 },
557	{ 0x3818, 0xc9 },
558	{ 0x381c, 0x10 },
559	{ 0x381d, 0xa0 },
560	{ 0x381e, 0x5  },
561	{ 0x381f, 0xb0 },
562	{ 0x3820, 0x0  },
563	{ 0x3821, 0x0  },
564	{ 0x3824, 0x11 },
565	{ 0x3a08, 0x1b },
566	{ 0x3a09, 0xc0 },
567	{ 0x3a0a, 0x17 },
568	{ 0x3a0b, 0x20 },
569	{ 0x3a0d, 0x2  },
570	{ 0x3a0e, 0x1  },
571	{ 0x401c, 0x4  },
572	{ 0x5682, 0x5  },
573	{ 0x5683, 0x0  },
574	{ 0x5686, 0x2  },
575	{ 0x5687, 0xcc },
576	{ 0x5001, 0x4f },
577	{ 0x589b, 0x6  },
578	{ 0x589a, 0xc5 },
579	{ 0x3503, 0x0  },
580	{ 0x460c, 0x20 },
581	{ 0x460b, 0x37 },
582	{ 0x471c, 0xd0 },
583	{ 0x471d, 0x5  },
584	{ 0x3815, 0x1  },
585	{ 0x3818, 0xc1 },
586	{ 0x501f, 0x0  },
587	{ 0x5002, 0xe0 },
588	{ 0x4300, 0x32 }, /* UYVY */
589	{ 0x3002, 0x1c },
590	{ 0x4800, 0x14 },
591	{ 0x4801, 0xf  },
592	{ 0x3007, 0x3b },
593	{ 0x300e, 0x4  },
594	{ 0x4803, 0x50 },
595	{ 0x3815, 0x1  },
596	{ 0x4713, 0x2  },
597	{ 0x4842, 0x1  },
598	{ 0x300f, 0xe  },
599	{ 0x3003, 0x3  },
600	{ 0x3003, 0x1  },
601	{ 0xffff, 0xff },
602};
603
604struct ov5642_datafmt {
605	u32	code;
606	enum v4l2_colorspace		colorspace;
607};
608
609struct ov5642 {
610	struct v4l2_subdev		subdev;
611	const struct ov5642_datafmt	*fmt;
612	struct v4l2_rect                crop_rect;
613	struct v4l2_clk			*clk;
614
615	/* blanking information */
616	int total_width;
617	int total_height;
618};
619
620static const struct ov5642_datafmt ov5642_colour_fmts[] = {
621	{MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
622};
623
624static struct ov5642 *to_ov5642(const struct i2c_client *client)
625{
626	return container_of(i2c_get_clientdata(client), struct ov5642, subdev);
627}
628
629/* Find a data format by a pixel code in an array */
630static const struct ov5642_datafmt
631			*ov5642_find_datafmt(u32 code)
632{
633	int i;
634
635	for (i = 0; i < ARRAY_SIZE(ov5642_colour_fmts); i++)
636		if (ov5642_colour_fmts[i].code == code)
637			return ov5642_colour_fmts + i;
638
639	return NULL;
640}
641
642static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
643{
644	int ret;
645	/* We have 16-bit i2c addresses - care for endianness */
646	unsigned char data[2] = { reg >> 8, reg & 0xff };
647
648	ret = i2c_master_send(client, data, 2);
649	if (ret < 2) {
650		dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
651			__func__, reg);
652		return ret < 0 ? ret : -EIO;
653	}
654
655	ret = i2c_master_recv(client, val, 1);
656	if (ret < 1) {
657		dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
658				__func__, reg);
659		return ret < 0 ? ret : -EIO;
660	}
661	return 0;
662}
663
664static int reg_write(struct i2c_client *client, u16 reg, u8 val)
665{
666	int ret;
667	unsigned char data[3] = { reg >> 8, reg & 0xff, val };
668
669	ret = i2c_master_send(client, data, 3);
670	if (ret < 3) {
671		dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
672			__func__, reg);
673		return ret < 0 ? ret : -EIO;
674	}
675
676	return 0;
677}
678
679/*
680 * convenience function to write 16 bit register values that are split up
681 * into two consecutive high and low parts
682 */
683static int reg_write16(struct i2c_client *client, u16 reg, u16 val16)
684{
685	int ret;
686
687	ret = reg_write(client, reg, val16 >> 8);
688	if (ret)
689		return ret;
690	return reg_write(client, reg + 1, val16 & 0x00ff);
691}
692
693#ifdef CONFIG_VIDEO_ADV_DEBUG
694static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
695{
696	struct i2c_client *client = v4l2_get_subdevdata(sd);
697	int ret;
698	u8 val;
699
700	if (reg->reg & ~0xffff)
701		return -EINVAL;
702
703	reg->size = 1;
704
705	ret = reg_read(client, reg->reg, &val);
706	if (!ret)
707		reg->val = (__u64)val;
708
709	return ret;
710}
711
712static int ov5642_set_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
713{
714	struct i2c_client *client = v4l2_get_subdevdata(sd);
715
716	if (reg->reg & ~0xffff || reg->val & ~0xff)
717		return -EINVAL;
718
719	return reg_write(client, reg->reg, reg->val);
720}
721#endif
722
723static int ov5642_write_array(struct i2c_client *client,
724				struct regval_list *vals)
725{
726	while (vals->reg_num != 0xffff || vals->value != 0xff) {
727		int ret = reg_write(client, vals->reg_num, vals->value);
728		if (ret < 0)
729			return ret;
730		vals++;
731	}
732	dev_dbg(&client->dev, "Register list loaded\n");
733	return 0;
734}
735
736static int ov5642_set_resolution(struct v4l2_subdev *sd)
737{
738	struct i2c_client *client = v4l2_get_subdevdata(sd);
739	struct ov5642 *priv = to_ov5642(client);
740	int width = priv->crop_rect.width;
741	int height = priv->crop_rect.height;
742	int total_width = priv->total_width;
743	int total_height = priv->total_height;
744	int start_x = (OV5642_SENSOR_SIZE_X - width) / 2;
745	int start_y = (OV5642_SENSOR_SIZE_Y - height) / 2;
746	int ret;
747
748	/*
749	 * This should set the starting point for cropping.
750	 * Doesn't work so far.
751	 */
752	ret = reg_write16(client, REG_WINDOW_START_X_HIGH, start_x);
753	if (!ret)
754		ret = reg_write16(client, REG_WINDOW_START_Y_HIGH, start_y);
755	if (!ret) {
756		priv->crop_rect.left = start_x;
757		priv->crop_rect.top = start_y;
758	}
759
760	if (!ret)
761		ret = reg_write16(client, REG_WINDOW_WIDTH_HIGH, width);
762	if (!ret)
763		ret = reg_write16(client, REG_WINDOW_HEIGHT_HIGH, height);
764	if (ret)
765		return ret;
766	priv->crop_rect.width = width;
767	priv->crop_rect.height = height;
768
769	/* Set the output window size. Only 1:1 scale is supported so far. */
770	ret = reg_write16(client, REG_OUT_WIDTH_HIGH, width);
771	if (!ret)
772		ret = reg_write16(client, REG_OUT_HEIGHT_HIGH, height);
773
774	/* Total width = output size + blanking */
775	if (!ret)
776		ret = reg_write16(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width);
777	if (!ret)
778		ret = reg_write16(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height);
779
780	/* Sets the window for AWB calculations */
781	if (!ret)
782		ret = reg_write16(client, REG_AVG_WINDOW_END_X_HIGH, width);
783	if (!ret)
784		ret = reg_write16(client, REG_AVG_WINDOW_END_Y_HIGH, height);
785
786	return ret;
787}
788
789static int ov5642_try_fmt(struct v4l2_subdev *sd,
790			  struct v4l2_mbus_framefmt *mf)
791{
792	struct i2c_client *client = v4l2_get_subdevdata(sd);
793	struct ov5642 *priv = to_ov5642(client);
794	const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
795
796	mf->width = priv->crop_rect.width;
797	mf->height = priv->crop_rect.height;
798
799	if (!fmt) {
800		mf->code	= ov5642_colour_fmts[0].code;
801		mf->colorspace	= ov5642_colour_fmts[0].colorspace;
802	}
803
804	mf->field	= V4L2_FIELD_NONE;
805
806	return 0;
807}
808
809static int ov5642_s_fmt(struct v4l2_subdev *sd,
810			struct v4l2_mbus_framefmt *mf)
811{
812	struct i2c_client *client = v4l2_get_subdevdata(sd);
813	struct ov5642 *priv = to_ov5642(client);
814
815	/* MIPI CSI could have changed the format, double-check */
816	if (!ov5642_find_datafmt(mf->code))
817		return -EINVAL;
818
819	ov5642_try_fmt(sd, mf);
820	priv->fmt = ov5642_find_datafmt(mf->code);
821
822	return 0;
823}
824
825static int ov5642_g_fmt(struct v4l2_subdev *sd,
826			struct v4l2_mbus_framefmt *mf)
827{
828	struct i2c_client *client = v4l2_get_subdevdata(sd);
829	struct ov5642 *priv = to_ov5642(client);
830
831	const struct ov5642_datafmt *fmt = priv->fmt;
832
833	mf->code	= fmt->code;
834	mf->colorspace	= fmt->colorspace;
835	mf->width	= priv->crop_rect.width;
836	mf->height	= priv->crop_rect.height;
837	mf->field	= V4L2_FIELD_NONE;
838
839	return 0;
840}
841
842static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
843			   u32 *code)
844{
845	if (index >= ARRAY_SIZE(ov5642_colour_fmts))
846		return -EINVAL;
847
848	*code = ov5642_colour_fmts[index].code;
849	return 0;
850}
851
852static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
853{
854	struct i2c_client *client = v4l2_get_subdevdata(sd);
855	struct ov5642 *priv = to_ov5642(client);
856	struct v4l2_rect rect = a->c;
857	int ret;
858
859	v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,
860			      &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0);
861
862	priv->crop_rect.width	= rect.width;
863	priv->crop_rect.height	= rect.height;
864	priv->total_width	= rect.width + BLANKING_EXTRA_WIDTH;
865	priv->total_height	= max_t(int, rect.height +
866							BLANKING_EXTRA_HEIGHT,
867							BLANKING_MIN_HEIGHT);
868	priv->crop_rect.width		= rect.width;
869	priv->crop_rect.height		= rect.height;
870
871	ret = ov5642_write_array(client, ov5642_default_regs_init);
872	if (!ret)
873		ret = ov5642_set_resolution(sd);
874	if (!ret)
875		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
876
877	return ret;
878}
879
880static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
881{
882	struct i2c_client *client = v4l2_get_subdevdata(sd);
883	struct ov5642 *priv = to_ov5642(client);
884	struct v4l2_rect *rect = &a->c;
885
886	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
887		return -EINVAL;
888
889	*rect = priv->crop_rect;
890
891	return 0;
892}
893
894static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
895{
896	a->bounds.left			= 0;
897	a->bounds.top			= 0;
898	a->bounds.width			= OV5642_MAX_WIDTH;
899	a->bounds.height		= OV5642_MAX_HEIGHT;
900	a->defrect			= a->bounds;
901	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
902	a->pixelaspect.numerator	= 1;
903	a->pixelaspect.denominator	= 1;
904
905	return 0;
906}
907
908static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
909				struct v4l2_mbus_config *cfg)
910{
911	cfg->type = V4L2_MBUS_CSI2;
912	cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
913					V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
914
915	return 0;
916}
917
918static int ov5642_s_power(struct v4l2_subdev *sd, int on)
919{
920	struct i2c_client *client = v4l2_get_subdevdata(sd);
921	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
922	struct ov5642 *priv = to_ov5642(client);
923	int ret;
924
925	if (!on)
926		return soc_camera_power_off(&client->dev, ssdd, priv->clk);
927
928	ret = soc_camera_power_on(&client->dev, ssdd, priv->clk);
929	if (ret < 0)
930		return ret;
931
932	ret = ov5642_write_array(client, ov5642_default_regs_init);
933	if (!ret)
934		ret = ov5642_set_resolution(sd);
935	if (!ret)
936		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
937
938	return ret;
939}
940
941static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
942	.s_mbus_fmt	= ov5642_s_fmt,
943	.g_mbus_fmt	= ov5642_g_fmt,
944	.try_mbus_fmt	= ov5642_try_fmt,
945	.enum_mbus_fmt	= ov5642_enum_fmt,
946	.s_crop		= ov5642_s_crop,
947	.g_crop		= ov5642_g_crop,
948	.cropcap	= ov5642_cropcap,
949	.g_mbus_config	= ov5642_g_mbus_config,
950};
951
952static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
953	.s_power	= ov5642_s_power,
954#ifdef CONFIG_VIDEO_ADV_DEBUG
955	.g_register	= ov5642_get_register,
956	.s_register	= ov5642_set_register,
957#endif
958};
959
960static struct v4l2_subdev_ops ov5642_subdev_ops = {
961	.core	= &ov5642_subdev_core_ops,
962	.video	= &ov5642_subdev_video_ops,
963};
964
965static int ov5642_video_probe(struct i2c_client *client)
966{
967	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
968	int ret;
969	u8 id_high, id_low;
970	u16 id;
971
972	ret = ov5642_s_power(subdev, 1);
973	if (ret < 0)
974		return ret;
975
976	/* Read sensor Model ID */
977	ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high);
978	if (ret < 0)
979		goto done;
980
981	id = id_high << 8;
982
983	ret = reg_read(client, REG_CHIP_ID_LOW, &id_low);
984	if (ret < 0)
985		goto done;
986
987	id |= id_low;
988
989	dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
990
991	if (id != 0x5642) {
992		ret = -ENODEV;
993		goto done;
994	}
995
996	ret = 0;
997
998done:
999	ov5642_s_power(subdev, 0);
1000	return ret;
1001}
1002
1003static int ov5642_probe(struct i2c_client *client,
1004			const struct i2c_device_id *did)
1005{
1006	struct ov5642 *priv;
1007	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
1008	int ret;
1009
1010	if (!ssdd) {
1011		dev_err(&client->dev, "OV5642: missing platform data!\n");
1012		return -EINVAL;
1013	}
1014
1015	priv = devm_kzalloc(&client->dev, sizeof(struct ov5642), GFP_KERNEL);
1016	if (!priv)
1017		return -ENOMEM;
1018
1019	v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
1020
1021	priv->fmt		= &ov5642_colour_fmts[0];
1022
1023	priv->crop_rect.width	= OV5642_DEFAULT_WIDTH;
1024	priv->crop_rect.height	= OV5642_DEFAULT_HEIGHT;
1025	priv->crop_rect.left	= (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2;
1026	priv->crop_rect.top	= (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2;
1027	priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
1028	priv->total_height = BLANKING_MIN_HEIGHT;
1029
1030	priv->clk = v4l2_clk_get(&client->dev, "mclk");
1031	if (IS_ERR(priv->clk))
1032		return PTR_ERR(priv->clk);
1033
1034	ret = ov5642_video_probe(client);
1035	if (ret < 0)
1036		v4l2_clk_put(priv->clk);
1037
1038	return ret;
1039}
1040
1041static int ov5642_remove(struct i2c_client *client)
1042{
1043	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
1044	struct ov5642 *priv = to_ov5642(client);
1045
1046	v4l2_clk_put(priv->clk);
1047	if (ssdd->free_bus)
1048		ssdd->free_bus(ssdd);
1049
1050	return 0;
1051}
1052
1053static const struct i2c_device_id ov5642_id[] = {
1054	{ "ov5642", 0 },
1055	{ }
1056};
1057MODULE_DEVICE_TABLE(i2c, ov5642_id);
1058
1059static struct i2c_driver ov5642_i2c_driver = {
1060	.driver = {
1061		.name = "ov5642",
1062	},
1063	.probe		= ov5642_probe,
1064	.remove		= ov5642_remove,
1065	.id_table	= ov5642_id,
1066};
1067
1068module_i2c_driver(ov5642_i2c_driver);
1069
1070MODULE_DESCRIPTION("Omnivision OV5642 Camera driver");
1071MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
1072MODULE_LICENSE("GPL v2");
1073