1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Driver for Renesas R-Car VIN
4 *
5 * Copyright (C) 2016 Renesas Electronics Corp.
6 * Copyright (C) 2011-2013 Renesas Solutions Corp.
7 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
8 * Copyright (C) 2008 Magnus Damm
9 *
10 * Based on the soc-camera rcar_vin driver
11 */
12
13#include <linux/delay.h>
14#include <linux/interrupt.h>
15#include <linux/pm_runtime.h>
16
17#include <media/videobuf2-dma-contig.h>
18
19#include "rcar-vin.h"
20
21/* -----------------------------------------------------------------------------
22 * HW Functions
23 */
24
25/* Register offsets for R-Car VIN */
26#define VNMC_REG	0x00	/* Video n Main Control Register */
27#define VNMS_REG	0x04	/* Video n Module Status Register */
28#define VNFC_REG	0x08	/* Video n Frame Capture Register */
29#define VNSLPRC_REG	0x0C	/* Video n Start Line Pre-Clip Register */
30#define VNELPRC_REG	0x10	/* Video n End Line Pre-Clip Register */
31#define VNSPPRC_REG	0x14	/* Video n Start Pixel Pre-Clip Register */
32#define VNEPPRC_REG	0x18	/* Video n End Pixel Pre-Clip Register */
33#define VNIS_REG	0x2C	/* Video n Image Stride Register */
34#define VNMB_REG(m)	(0x30 + ((m) << 2)) /* Video n Memory Base m Register */
35#define VNIE_REG	0x40	/* Video n Interrupt Enable Register */
36#define VNINTS_REG	0x44	/* Video n Interrupt Status Register */
37#define VNSI_REG	0x48	/* Video n Scanline Interrupt Register */
38#define VNMTC_REG	0x4C	/* Video n Memory Transfer Control Register */
39#define VNDMR_REG	0x58	/* Video n Data Mode Register */
40#define VNDMR2_REG	0x5C	/* Video n Data Mode Register 2 */
41#define VNUVAOF_REG	0x60	/* Video n UV Address Offset Register */
42
43/* Register offsets specific for Gen2 */
44#define VNSLPOC_REG	0x1C	/* Video n Start Line Post-Clip Register */
45#define VNELPOC_REG	0x20	/* Video n End Line Post-Clip Register */
46#define VNSPPOC_REG	0x24	/* Video n Start Pixel Post-Clip Register */
47#define VNEPPOC_REG	0x28	/* Video n End Pixel Post-Clip Register */
48#define VNYS_REG	0x50	/* Video n Y Scale Register */
49#define VNXS_REG	0x54	/* Video n X Scale Register */
50#define VNC1A_REG	0x80	/* Video n Coefficient Set C1A Register */
51#define VNC1B_REG	0x84	/* Video n Coefficient Set C1B Register */
52#define VNC1C_REG	0x88	/* Video n Coefficient Set C1C Register */
53#define VNC2A_REG	0x90	/* Video n Coefficient Set C2A Register */
54#define VNC2B_REG	0x94	/* Video n Coefficient Set C2B Register */
55#define VNC2C_REG	0x98	/* Video n Coefficient Set C2C Register */
56#define VNC3A_REG	0xA0	/* Video n Coefficient Set C3A Register */
57#define VNC3B_REG	0xA4	/* Video n Coefficient Set C3B Register */
58#define VNC3C_REG	0xA8	/* Video n Coefficient Set C3C Register */
59#define VNC4A_REG	0xB0	/* Video n Coefficient Set C4A Register */
60#define VNC4B_REG	0xB4	/* Video n Coefficient Set C4B Register */
61#define VNC4C_REG	0xB8	/* Video n Coefficient Set C4C Register */
62#define VNC5A_REG	0xC0	/* Video n Coefficient Set C5A Register */
63#define VNC5B_REG	0xC4	/* Video n Coefficient Set C5B Register */
64#define VNC5C_REG	0xC8	/* Video n Coefficient Set C5C Register */
65#define VNC6A_REG	0xD0	/* Video n Coefficient Set C6A Register */
66#define VNC6B_REG	0xD4	/* Video n Coefficient Set C6B Register */
67#define VNC6C_REG	0xD8	/* Video n Coefficient Set C6C Register */
68#define VNC7A_REG	0xE0	/* Video n Coefficient Set C7A Register */
69#define VNC7B_REG	0xE4	/* Video n Coefficient Set C7B Register */
70#define VNC7C_REG	0xE8	/* Video n Coefficient Set C7C Register */
71#define VNC8A_REG	0xF0	/* Video n Coefficient Set C8A Register */
72#define VNC8B_REG	0xF4	/* Video n Coefficient Set C8B Register */
73#define VNC8C_REG	0xF8	/* Video n Coefficient Set C8C Register */
74
75/* Register offsets specific for Gen3 */
76#define VNCSI_IFMD_REG		0x20 /* Video n CSI2 Interface Mode Register */
77
78/* Register bit fields for R-Car VIN */
79/* Video n Main Control Register bits */
80#define VNMC_DPINE		(1 << 27) /* Gen3 specific */
81#define VNMC_SCLE		(1 << 26) /* Gen3 specific */
82#define VNMC_FOC		(1 << 21)
83#define VNMC_YCAL		(1 << 19)
84#define VNMC_INF_YUV8_BT656	(0 << 16)
85#define VNMC_INF_YUV8_BT601	(1 << 16)
86#define VNMC_INF_YUV10_BT656	(2 << 16)
87#define VNMC_INF_YUV10_BT601	(3 << 16)
88#define VNMC_INF_RAW8		(4 << 16)
89#define VNMC_INF_YUV16		(5 << 16)
90#define VNMC_INF_RGB888		(6 << 16)
91#define VNMC_VUP		(1 << 10)
92#define VNMC_IM_ODD		(0 << 3)
93#define VNMC_IM_ODD_EVEN	(1 << 3)
94#define VNMC_IM_EVEN		(2 << 3)
95#define VNMC_IM_FULL		(3 << 3)
96#define VNMC_BPS		(1 << 1)
97#define VNMC_ME			(1 << 0)
98
99/* Video n Module Status Register bits */
100#define VNMS_FBS_MASK		(3 << 3)
101#define VNMS_FBS_SHIFT		3
102#define VNMS_FS			(1 << 2)
103#define VNMS_AV			(1 << 1)
104#define VNMS_CA			(1 << 0)
105
106/* Video n Frame Capture Register bits */
107#define VNFC_C_FRAME		(1 << 1)
108#define VNFC_S_FRAME		(1 << 0)
109
110/* Video n Interrupt Enable Register bits */
111#define VNIE_FIE		(1 << 4)
112#define VNIE_EFE		(1 << 1)
113
114/* Video n Data Mode Register bits */
115#define VNDMR_A8BIT(n)		(((n) & 0xff) << 24)
116#define VNDMR_A8BIT_MASK	(0xff << 24)
117#define VNDMR_EXRGB		(1 << 8)
118#define VNDMR_BPSM		(1 << 4)
119#define VNDMR_ABIT		(1 << 2)
120#define VNDMR_DTMD_YCSEP	(1 << 1)
121#define VNDMR_DTMD_ARGB		(1 << 0)
122#define VNDMR_DTMD_YCSEP_420	(3 << 0)
123
124/* Video n Data Mode Register 2 bits */
125#define VNDMR2_VPS		(1 << 30)
126#define VNDMR2_HPS		(1 << 29)
127#define VNDMR2_CES		(1 << 28)
128#define VNDMR2_YDS		(1 << 22)
129#define VNDMR2_FTEV		(1 << 17)
130#define VNDMR2_VLV(n)		((n & 0xf) << 12)
131
132/* Video n CSI2 Interface Mode Register (Gen3) */
133#define VNCSI_IFMD_DES1		(1 << 26)
134#define VNCSI_IFMD_DES0		(1 << 25)
135#define VNCSI_IFMD_CSI_CHSEL(n) (((n) & 0xf) << 0)
136#define VNCSI_IFMD_CSI_CHSEL_MASK 0xf
137
138struct rvin_buffer {
139	struct vb2_v4l2_buffer vb;
140	struct list_head list;
141};
142
143#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
144					       struct rvin_buffer, \
145					       vb)->list)
146
147static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
148{
149	iowrite32(value, vin->base + offset);
150}
151
152static u32 rvin_read(struct rvin_dev *vin, u32 offset)
153{
154	return ioread32(vin->base + offset);
155}
156
157/* -----------------------------------------------------------------------------
158 * Crop and Scaling Gen2
159 */
160
161struct vin_coeff {
162	unsigned short xs_value;
163	u32 coeff_set[24];
164};
165
166static const struct vin_coeff vin_coeff_set[] = {
167	{ 0x0000, {
168			  0x00000000, 0x00000000, 0x00000000,
169			  0x00000000, 0x00000000, 0x00000000,
170			  0x00000000, 0x00000000, 0x00000000,
171			  0x00000000, 0x00000000, 0x00000000,
172			  0x00000000, 0x00000000, 0x00000000,
173			  0x00000000, 0x00000000, 0x00000000,
174			  0x00000000, 0x00000000, 0x00000000,
175			  0x00000000, 0x00000000, 0x00000000 },
176	},
177	{ 0x1000, {
178			  0x000fa400, 0x000fa400, 0x09625902,
179			  0x000003f8, 0x00000403, 0x3de0d9f0,
180			  0x001fffed, 0x00000804, 0x3cc1f9c3,
181			  0x001003de, 0x00000c01, 0x3cb34d7f,
182			  0x002003d2, 0x00000c00, 0x3d24a92d,
183			  0x00200bca, 0x00000bff, 0x3df600d2,
184			  0x002013cc, 0x000007ff, 0x3ed70c7e,
185			  0x00100fde, 0x00000000, 0x3f87c036 },
186	},
187	{ 0x1200, {
188			  0x002ffff1, 0x002ffff1, 0x02a0a9c8,
189			  0x002003e7, 0x001ffffa, 0x000185bc,
190			  0x002007dc, 0x000003ff, 0x3e52859c,
191			  0x00200bd4, 0x00000002, 0x3d53996b,
192			  0x00100fd0, 0x00000403, 0x3d04ad2d,
193			  0x00000bd5, 0x00000403, 0x3d35ace7,
194			  0x3ff003e4, 0x00000801, 0x3dc674a1,
195			  0x3fffe800, 0x00000800, 0x3e76f461 },
196	},
197	{ 0x1400, {
198			  0x00100be3, 0x00100be3, 0x04d1359a,
199			  0x00000fdb, 0x002003ed, 0x0211fd93,
200			  0x00000fd6, 0x002003f4, 0x0002d97b,
201			  0x000007d6, 0x002ffffb, 0x3e93b956,
202			  0x3ff003da, 0x001003ff, 0x3db49926,
203			  0x3fffefe9, 0x00100001, 0x3d655cee,
204			  0x3fffd400, 0x00000003, 0x3d65f4b6,
205			  0x000fb421, 0x00000402, 0x3dc6547e },
206	},
207	{ 0x1600, {
208			  0x00000bdd, 0x00000bdd, 0x06519578,
209			  0x3ff007da, 0x00000be3, 0x03c24973,
210			  0x3ff003d9, 0x00000be9, 0x01b30d5f,
211			  0x3ffff7df, 0x001003f1, 0x0003c542,
212			  0x000fdfec, 0x001003f7, 0x3ec4711d,
213			  0x000fc400, 0x002ffffd, 0x3df504f1,
214			  0x001fa81a, 0x002ffc00, 0x3d957cc2,
215			  0x002f8c3c, 0x00100000, 0x3db5c891 },
216	},
217	{ 0x1800, {
218			  0x3ff003dc, 0x3ff003dc, 0x0791e558,
219			  0x000ff7dd, 0x3ff007de, 0x05328554,
220			  0x000fe7e3, 0x3ff00be2, 0x03232546,
221			  0x000fd7ee, 0x000007e9, 0x0143bd30,
222			  0x001fb800, 0x000007ee, 0x00044511,
223			  0x002fa015, 0x000007f4, 0x3ef4bcee,
224			  0x002f8832, 0x001003f9, 0x3e4514c7,
225			  0x001f7853, 0x001003fd, 0x3de54c9f },
226	},
227	{ 0x1a00, {
228			  0x000fefe0, 0x000fefe0, 0x08721d3c,
229			  0x001fdbe7, 0x000ffbde, 0x0652a139,
230			  0x001fcbf0, 0x000003df, 0x0463292e,
231			  0x002fb3ff, 0x3ff007e3, 0x0293a91d,
232			  0x002f9c12, 0x3ff00be7, 0x01241905,
233			  0x001f8c29, 0x000007ed, 0x3fe470eb,
234			  0x000f7c46, 0x000007f2, 0x3f04b8ca,
235			  0x3fef7865, 0x000007f6, 0x3e74e4a8 },
236	},
237	{ 0x1c00, {
238			  0x001fd3e9, 0x001fd3e9, 0x08f23d26,
239			  0x002fbff3, 0x001fe3e4, 0x0712ad23,
240			  0x002fa800, 0x000ff3e0, 0x05631d1b,
241			  0x001f9810, 0x000ffbe1, 0x03b3890d,
242			  0x000f8c23, 0x000003e3, 0x0233e8fa,
243			  0x3fef843b, 0x000003e7, 0x00f430e4,
244			  0x3fbf8456, 0x3ff00bea, 0x00046cc8,
245			  0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
246	},
247	{ 0x1e00, {
248			  0x001fbbf4, 0x001fbbf4, 0x09425112,
249			  0x001fa800, 0x002fc7ed, 0x0792b110,
250			  0x000f980e, 0x001fdbe6, 0x0613110a,
251			  0x3fff8c20, 0x001fe7e3, 0x04a368fd,
252			  0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
253			  0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
254			  0x3f5f9c61, 0x000003e6, 0x00e428c5,
255			  0x3f1fb07b, 0x000003eb, 0x3fe440af },
256	},
257	{ 0x2000, {
258			  0x000fa400, 0x000fa400, 0x09625902,
259			  0x3fff980c, 0x001fb7f5, 0x0812b0ff,
260			  0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
261			  0x3faf902d, 0x001fd3e8, 0x055348f1,
262			  0x3f7f983f, 0x001fe3e5, 0x04038ce3,
263			  0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
264			  0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
265			  0x3ecfd880, 0x000fffe6, 0x00c404ac },
266	},
267	{ 0x2200, {
268			  0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
269			  0x3fbf9818, 0x3fffa400, 0x0842a8f1,
270			  0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
271			  0x3f5fa037, 0x000fc3ef, 0x05d330e4,
272			  0x3f2fac49, 0x001fcfea, 0x04a364d9,
273			  0x3effc05c, 0x001fdbe7, 0x038394ca,
274			  0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
275			  0x3ea00083, 0x001fefe6, 0x0183c0a9 },
276	},
277	{ 0x2400, {
278			  0x3f9fa014, 0x3f9fa014, 0x098260e6,
279			  0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
280			  0x3f4fa431, 0x3fefa400, 0x0742d8e1,
281			  0x3f1fb440, 0x3fffb3f8, 0x062310d9,
282			  0x3eefc850, 0x000fbbf2, 0x050340d0,
283			  0x3ecfe062, 0x000fcbec, 0x041364c2,
284			  0x3ea00073, 0x001fd3ea, 0x03037cb5,
285			  0x3e902086, 0x001fdfe8, 0x022388a5 },
286	},
287	{ 0x2600, {
288			  0x3f5fa81e, 0x3f5fa81e, 0x096258da,
289			  0x3f3fac2b, 0x3f8fa412, 0x088290d8,
290			  0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
291			  0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
292			  0x3ecfe456, 0x3fefaffa, 0x05531cc6,
293			  0x3eb00066, 0x3fffbbf3, 0x047334bb,
294			  0x3ea01c77, 0x000fc7ee, 0x039348ae,
295			  0x3ea04486, 0x000fd3eb, 0x02b350a1 },
296	},
297	{ 0x2800, {
298			  0x3f2fb426, 0x3f2fb426, 0x094250ce,
299			  0x3f0fc032, 0x3f4fac1b, 0x086284cd,
300			  0x3eefd040, 0x3f7fa811, 0x0782acc9,
301			  0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
302			  0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
303			  0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
304			  0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
305			  0x3ec06884, 0x000fbff2, 0x03031c9e },
306	},
307	{ 0x2a00, {
308			  0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
309			  0x3eefd439, 0x3f2fb822, 0x08526cc2,
310			  0x3edfe845, 0x3f4fb018, 0x078294bf,
311			  0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
312			  0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
313			  0x3ec0386b, 0x3fafac00, 0x0502e8ac,
314			  0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
315			  0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
316	},
317	{ 0x2c00, {
318			  0x3eefdc31, 0x3eefdc31, 0x08e238b8,
319			  0x3edfec3d, 0x3f0fc828, 0x082258b9,
320			  0x3ed00049, 0x3f1fc01e, 0x077278b6,
321			  0x3ed01455, 0x3f3fb815, 0x06c294b2,
322			  0x3ed03460, 0x3f5fb40d, 0x0602acac,
323			  0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
324			  0x3f107476, 0x3f9fb400, 0x0472c89d,
325			  0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
326	},
327	{ 0x2e00, {
328			  0x3eefec37, 0x3eefec37, 0x088220b0,
329			  0x3ee00041, 0x3effdc2d, 0x07f244ae,
330			  0x3ee0144c, 0x3f0fd023, 0x07625cad,
331			  0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
332			  0x3f004861, 0x3f3fbc13, 0x060288a6,
333			  0x3f20686b, 0x3f5fb80c, 0x05529c9e,
334			  0x3f408c74, 0x3f6fb805, 0x04b2ac96,
335			  0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
336	},
337	{ 0x3000, {
338			  0x3ef0003a, 0x3ef0003a, 0x084210a6,
339			  0x3ef01045, 0x3effec32, 0x07b228a7,
340			  0x3f00284e, 0x3f0fdc29, 0x073244a4,
341			  0x3f104058, 0x3f0fd420, 0x06a258a2,
342			  0x3f305c62, 0x3f2fc818, 0x0612689d,
343			  0x3f508069, 0x3f3fc011, 0x05728496,
344			  0x3f80a072, 0x3f4fc00a, 0x04d28c90,
345			  0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
346	},
347	{ 0x3200, {
348			  0x3f00103e, 0x3f00103e, 0x07f1fc9e,
349			  0x3f102447, 0x3f000035, 0x0782149d,
350			  0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
351			  0x3f405458, 0x3f0fe424, 0x06924099,
352			  0x3f607061, 0x3f1fd41d, 0x06024c97,
353			  0x3f909068, 0x3f2fcc16, 0x05726490,
354			  0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
355			  0x0000d077, 0x3f4fc409, 0x04627484 },
356	},
357	{ 0x3400, {
358			  0x3f202040, 0x3f202040, 0x07a1e898,
359			  0x3f303449, 0x3f100c38, 0x0741fc98,
360			  0x3f504c50, 0x3f10002f, 0x06e21495,
361			  0x3f706459, 0x3f1ff028, 0x06722492,
362			  0x3fa08060, 0x3f1fe421, 0x05f2348f,
363			  0x3fd09c67, 0x3f1fdc19, 0x05824c89,
364			  0x0000bc6e, 0x3f2fd014, 0x04f25086,
365			  0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
366	},
367	{ 0x3600, {
368			  0x3f403042, 0x3f403042, 0x0761d890,
369			  0x3f504848, 0x3f301c3b, 0x0701f090,
370			  0x3f805c50, 0x3f200c33, 0x06a2008f,
371			  0x3fa07458, 0x3f10002b, 0x06520c8d,
372			  0x3fd0905e, 0x3f1ff424, 0x05e22089,
373			  0x0000ac65, 0x3f1fe81d, 0x05823483,
374			  0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
375			  0x0080e871, 0x3f2fd412, 0x0482407c },
376	},
377	{ 0x3800, {
378			  0x3f604043, 0x3f604043, 0x0721c88a,
379			  0x3f80544a, 0x3f502c3c, 0x06d1d88a,
380			  0x3fb06851, 0x3f301c35, 0x0681e889,
381			  0x3fd08456, 0x3f30082f, 0x0611fc88,
382			  0x00009c5d, 0x3f200027, 0x05d20884,
383			  0x0030b863, 0x3f2ff421, 0x05621880,
384			  0x0070d468, 0x3f2fe81b, 0x0502247c,
385			  0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
386	},
387	{ 0x3a00, {
388			  0x3f904c44, 0x3f904c44, 0x06e1b884,
389			  0x3fb0604a, 0x3f70383e, 0x0691c885,
390			  0x3fe07451, 0x3f502c36, 0x0661d483,
391			  0x00009055, 0x3f401831, 0x0601ec81,
392			  0x0030a85b, 0x3f300c2a, 0x05b1f480,
393			  0x0070c061, 0x3f300024, 0x0562047a,
394			  0x00b0d867, 0x3f3ff41e, 0x05020c77,
395			  0x00f0f46b, 0x3f2fec19, 0x04a21474 },
396	},
397	{ 0x3c00, {
398			  0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
399			  0x3fe06c4b, 0x3f902c3f, 0x0681c081,
400			  0x0000844f, 0x3f703838, 0x0631cc7d,
401			  0x00309855, 0x3f602433, 0x05d1d47e,
402			  0x0060b459, 0x3f50142e, 0x0581e47b,
403			  0x00a0c85f, 0x3f400828, 0x0531f078,
404			  0x00e0e064, 0x3f300021, 0x0501fc73,
405			  0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
406	},
407	{ 0x3e00, {
408			  0x3fe06444, 0x3fe06444, 0x0681a07a,
409			  0x00007849, 0x3fc0503f, 0x0641b07a,
410			  0x0020904d, 0x3fa0403a, 0x05f1c07a,
411			  0x0060a453, 0x3f803034, 0x05c1c878,
412			  0x0090b858, 0x3f70202f, 0x0571d477,
413			  0x00d0d05d, 0x3f501829, 0x0531e073,
414			  0x0110e462, 0x3f500825, 0x04e1e471,
415			  0x01510065, 0x3f40001f, 0x04a1f06d },
416	},
417	{ 0x4000, {
418			  0x00007044, 0x00007044, 0x06519476,
419			  0x00208448, 0x3fe05c3f, 0x0621a476,
420			  0x0050984d, 0x3fc04c3a, 0x05e1b075,
421			  0x0080ac52, 0x3fa03c35, 0x05a1b875,
422			  0x00c0c056, 0x3f803030, 0x0561c473,
423			  0x0100d45b, 0x3f70202b, 0x0521d46f,
424			  0x0140e860, 0x3f601427, 0x04d1d46e,
425			  0x01810064, 0x3f500822, 0x0491dc6b },
426	},
427	{ 0x5000, {
428			  0x0110a442, 0x0110a442, 0x0551545e,
429			  0x0140b045, 0x00e0983f, 0x0531585f,
430			  0x0160c047, 0x00c08c3c, 0x0511645e,
431			  0x0190cc4a, 0x00908039, 0x04f1685f,
432			  0x01c0dc4c, 0x00707436, 0x04d1705e,
433			  0x0200e850, 0x00506833, 0x04b1785b,
434			  0x0230f453, 0x00305c30, 0x0491805a,
435			  0x02710056, 0x0010542d, 0x04718059 },
436	},
437	{ 0x6000, {
438			  0x01c0bc40, 0x01c0bc40, 0x04c13052,
439			  0x01e0c841, 0x01a0b43d, 0x04c13851,
440			  0x0210cc44, 0x0180a83c, 0x04a13453,
441			  0x0230d845, 0x0160a03a, 0x04913c52,
442			  0x0260e047, 0x01409838, 0x04714052,
443			  0x0280ec49, 0x01208c37, 0x04514c50,
444			  0x02b0f44b, 0x01008435, 0x04414c50,
445			  0x02d1004c, 0x00e07c33, 0x0431544f },
446	},
447	{ 0x7000, {
448			  0x0230c83e, 0x0230c83e, 0x04711c4c,
449			  0x0250d03f, 0x0210c43c, 0x0471204b,
450			  0x0270d840, 0x0200b83c, 0x0451244b,
451			  0x0290dc42, 0x01e0b43a, 0x0441244c,
452			  0x02b0e443, 0x01c0b038, 0x0441284b,
453			  0x02d0ec44, 0x01b0a438, 0x0421304a,
454			  0x02f0f445, 0x0190a036, 0x04213449,
455			  0x0310f847, 0x01709c34, 0x04213848 },
456	},
457	{ 0x8000, {
458			  0x0280d03d, 0x0280d03d, 0x04310c48,
459			  0x02a0d43e, 0x0270c83c, 0x04311047,
460			  0x02b0dc3e, 0x0250c83a, 0x04311447,
461			  0x02d0e040, 0x0240c03a, 0x04211446,
462			  0x02e0e840, 0x0220bc39, 0x04111847,
463			  0x0300e842, 0x0210b438, 0x04012445,
464			  0x0310f043, 0x0200b037, 0x04012045,
465			  0x0330f444, 0x01e0ac36, 0x03f12445 },
466	},
467	{ 0xefff, {
468			  0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
469			  0x0340e03a, 0x0330e039, 0x03c0f03e,
470			  0x0350e03b, 0x0330dc39, 0x03c0ec3e,
471			  0x0350e43a, 0x0320dc38, 0x03c0f43e,
472			  0x0360e43b, 0x0320d839, 0x03b0f03e,
473			  0x0360e83b, 0x0310d838, 0x03c0fc3b,
474			  0x0370e83b, 0x0310d439, 0x03a0f83d,
475			  0x0370e83c, 0x0300d438, 0x03b0fc3c },
476	}
477};
478
479static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
480{
481	int i;
482	const struct vin_coeff *p_prev_set = NULL;
483	const struct vin_coeff *p_set = NULL;
484
485	/* Look for suitable coefficient values */
486	for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
487		p_prev_set = p_set;
488		p_set = &vin_coeff_set[i];
489
490		if (xs < p_set->xs_value)
491			break;
492	}
493
494	/* Use previous value if its XS value is closer */
495	if (p_prev_set &&
496	    xs - p_prev_set->xs_value < p_set->xs_value - xs)
497		p_set = p_prev_set;
498
499	/* Set coefficient registers */
500	rvin_write(vin, p_set->coeff_set[0], VNC1A_REG);
501	rvin_write(vin, p_set->coeff_set[1], VNC1B_REG);
502	rvin_write(vin, p_set->coeff_set[2], VNC1C_REG);
503
504	rvin_write(vin, p_set->coeff_set[3], VNC2A_REG);
505	rvin_write(vin, p_set->coeff_set[4], VNC2B_REG);
506	rvin_write(vin, p_set->coeff_set[5], VNC2C_REG);
507
508	rvin_write(vin, p_set->coeff_set[6], VNC3A_REG);
509	rvin_write(vin, p_set->coeff_set[7], VNC3B_REG);
510	rvin_write(vin, p_set->coeff_set[8], VNC3C_REG);
511
512	rvin_write(vin, p_set->coeff_set[9], VNC4A_REG);
513	rvin_write(vin, p_set->coeff_set[10], VNC4B_REG);
514	rvin_write(vin, p_set->coeff_set[11], VNC4C_REG);
515
516	rvin_write(vin, p_set->coeff_set[12], VNC5A_REG);
517	rvin_write(vin, p_set->coeff_set[13], VNC5B_REG);
518	rvin_write(vin, p_set->coeff_set[14], VNC5C_REG);
519
520	rvin_write(vin, p_set->coeff_set[15], VNC6A_REG);
521	rvin_write(vin, p_set->coeff_set[16], VNC6B_REG);
522	rvin_write(vin, p_set->coeff_set[17], VNC6C_REG);
523
524	rvin_write(vin, p_set->coeff_set[18], VNC7A_REG);
525	rvin_write(vin, p_set->coeff_set[19], VNC7B_REG);
526	rvin_write(vin, p_set->coeff_set[20], VNC7C_REG);
527
528	rvin_write(vin, p_set->coeff_set[21], VNC8A_REG);
529	rvin_write(vin, p_set->coeff_set[22], VNC8B_REG);
530	rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
531}
532
533static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
534{
535	unsigned int crop_height;
536	u32 xs, ys;
537
538	/* Set scaling coefficient */
539	crop_height = vin->crop.height;
540	if (V4L2_FIELD_HAS_BOTH(vin->format.field))
541		crop_height *= 2;
542
543	ys = 0;
544	if (crop_height != vin->compose.height)
545		ys = (4096 * crop_height) / vin->compose.height;
546	rvin_write(vin, ys, VNYS_REG);
547
548	xs = 0;
549	if (vin->crop.width != vin->compose.width)
550		xs = (4096 * vin->crop.width) / vin->compose.width;
551
552	/* Horizontal upscaling is up to double size */
553	if (xs > 0 && xs < 2048)
554		xs = 2048;
555
556	rvin_write(vin, xs, VNXS_REG);
557
558	/* Horizontal upscaling is done out by scaling down from double size */
559	if (xs < 4096)
560		xs *= 2;
561
562	rvin_set_coeff(vin, xs);
563
564	/* Set Start/End Pixel/Line Post-Clip */
565	rvin_write(vin, 0, VNSPPOC_REG);
566	rvin_write(vin, 0, VNSLPOC_REG);
567	rvin_write(vin, vin->format.width - 1, VNEPPOC_REG);
568
569	if (V4L2_FIELD_HAS_BOTH(vin->format.field))
570		rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG);
571	else
572		rvin_write(vin, vin->format.height - 1, VNELPOC_REG);
573
574	vin_dbg(vin,
575		"Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n",
576		vin->crop.width, vin->crop.height, vin->crop.left,
577		vin->crop.top, ys, xs, vin->format.width, vin->format.height,
578		0, 0);
579}
580
581void rvin_crop_scale_comp(struct rvin_dev *vin)
582{
583	const struct rvin_video_format *fmt;
584	u32 stride;
585
586	/* Set Start/End Pixel/Line Pre-Clip */
587	rvin_write(vin, vin->crop.left, VNSPPRC_REG);
588	rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
589	rvin_write(vin, vin->crop.top, VNSLPRC_REG);
590	rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
591
592	/* TODO: Add support for the UDS scaler. */
593	if (vin->info->model != RCAR_GEN3)
594		rvin_crop_scale_comp_gen2(vin);
595
596	fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
597	stride = vin->format.bytesperline / fmt->bpp;
598
599	/* For RAW8 format bpp is 1, but the hardware process RAW8
600	 * format in 2 pixel unit hence configure VNIS_REG as stride / 2.
601	 */
602	switch (vin->format.pixelformat) {
603	case V4L2_PIX_FMT_SBGGR8:
604	case V4L2_PIX_FMT_SGBRG8:
605	case V4L2_PIX_FMT_SGRBG8:
606	case V4L2_PIX_FMT_SRGGB8:
607		stride /= 2;
608		break;
609	default:
610		break;
611	}
612
613	rvin_write(vin, stride, VNIS_REG);
614}
615
616/* -----------------------------------------------------------------------------
617 * Hardware setup
618 */
619
620static int rvin_setup(struct rvin_dev *vin)
621{
622	u32 vnmc, dmr, dmr2, interrupts;
623	bool progressive = false, output_is_yuv = false, input_is_yuv = false;
624
625	switch (vin->format.field) {
626	case V4L2_FIELD_TOP:
627		vnmc = VNMC_IM_ODD;
628		break;
629	case V4L2_FIELD_BOTTOM:
630		vnmc = VNMC_IM_EVEN;
631		break;
632	case V4L2_FIELD_INTERLACED:
633		/* Default to TB */
634		vnmc = VNMC_IM_FULL;
635		/* Use BT if video standard can be read and is 60 Hz format */
636		if (!vin->info->use_mc && vin->std & V4L2_STD_525_60)
637			vnmc = VNMC_IM_FULL | VNMC_FOC;
638		break;
639	case V4L2_FIELD_INTERLACED_TB:
640		vnmc = VNMC_IM_FULL;
641		break;
642	case V4L2_FIELD_INTERLACED_BT:
643		vnmc = VNMC_IM_FULL | VNMC_FOC;
644		break;
645	case V4L2_FIELD_SEQ_TB:
646	case V4L2_FIELD_SEQ_BT:
647	case V4L2_FIELD_NONE:
648	case V4L2_FIELD_ALTERNATE:
649		vnmc = VNMC_IM_ODD_EVEN;
650		progressive = true;
651		break;
652	default:
653		vnmc = VNMC_IM_ODD;
654		break;
655	}
656
657	/*
658	 * Input interface
659	 */
660	switch (vin->mbus_code) {
661	case MEDIA_BUS_FMT_YUYV8_1X16:
662		/* BT.601/BT.1358 16bit YCbCr422 */
663		vnmc |= VNMC_INF_YUV16;
664		input_is_yuv = true;
665		break;
666	case MEDIA_BUS_FMT_UYVY8_1X16:
667		vnmc |= VNMC_INF_YUV16 | VNMC_YCAL;
668		input_is_yuv = true;
669		break;
670	case MEDIA_BUS_FMT_UYVY8_2X8:
671		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
672		if (!vin->is_csi &&
673		    vin->parallel->mbus_type == V4L2_MBUS_BT656)
674			vnmc |= VNMC_INF_YUV8_BT656;
675		else
676			vnmc |= VNMC_INF_YUV8_BT601;
677
678		input_is_yuv = true;
679		break;
680	case MEDIA_BUS_FMT_RGB888_1X24:
681		vnmc |= VNMC_INF_RGB888;
682		break;
683	case MEDIA_BUS_FMT_UYVY10_2X10:
684		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
685		if (!vin->is_csi &&
686		    vin->parallel->mbus_type == V4L2_MBUS_BT656)
687			vnmc |= VNMC_INF_YUV10_BT656;
688		else
689			vnmc |= VNMC_INF_YUV10_BT601;
690
691		input_is_yuv = true;
692		break;
693	case MEDIA_BUS_FMT_SBGGR8_1X8:
694	case MEDIA_BUS_FMT_SGBRG8_1X8:
695	case MEDIA_BUS_FMT_SGRBG8_1X8:
696	case MEDIA_BUS_FMT_SRGGB8_1X8:
697		vnmc |= VNMC_INF_RAW8;
698		break;
699	default:
700		break;
701	}
702
703	/* Enable VSYNC Field Toggle mode after one VSYNC input */
704	if (vin->info->model == RCAR_GEN3)
705		dmr2 = VNDMR2_FTEV;
706	else
707		dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
708
709	if (!vin->is_csi) {
710		/* Hsync Signal Polarity Select */
711		if (!(vin->parallel->bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
712			dmr2 |= VNDMR2_HPS;
713
714		/* Vsync Signal Polarity Select */
715		if (!(vin->parallel->bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
716			dmr2 |= VNDMR2_VPS;
717
718		/* Data Enable Polarity Select */
719		if (vin->parallel->bus.flags & V4L2_MBUS_DATA_ENABLE_LOW)
720			dmr2 |= VNDMR2_CES;
721
722		switch (vin->mbus_code) {
723		case MEDIA_BUS_FMT_UYVY8_2X8:
724			if (vin->parallel->bus.bus_width == 8 &&
725			    vin->parallel->bus.data_shift == 8)
726				dmr2 |= VNDMR2_YDS;
727			break;
728		default:
729			break;
730		}
731	}
732
733	/*
734	 * Output format
735	 */
736	switch (vin->format.pixelformat) {
737	case V4L2_PIX_FMT_NV12:
738	case V4L2_PIX_FMT_NV16:
739		rvin_write(vin,
740			   ALIGN(vin->format.bytesperline * vin->format.height,
741				 0x80), VNUVAOF_REG);
742		dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ?
743			VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP;
744		output_is_yuv = true;
745		break;
746	case V4L2_PIX_FMT_YUYV:
747		dmr = VNDMR_BPSM;
748		output_is_yuv = true;
749		break;
750	case V4L2_PIX_FMT_UYVY:
751		dmr = 0;
752		output_is_yuv = true;
753		break;
754	case V4L2_PIX_FMT_XRGB555:
755		dmr = VNDMR_DTMD_ARGB;
756		break;
757	case V4L2_PIX_FMT_RGB565:
758		dmr = 0;
759		break;
760	case V4L2_PIX_FMT_XBGR32:
761		/* Note: not supported on M1 */
762		dmr = VNDMR_EXRGB;
763		break;
764	case V4L2_PIX_FMT_ARGB555:
765		dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB;
766		break;
767	case V4L2_PIX_FMT_ABGR32:
768		dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB;
769		break;
770	case V4L2_PIX_FMT_SBGGR8:
771	case V4L2_PIX_FMT_SGBRG8:
772	case V4L2_PIX_FMT_SGRBG8:
773	case V4L2_PIX_FMT_SRGGB8:
774		dmr = 0;
775		break;
776	default:
777		vin_err(vin, "Invalid pixelformat (0x%x)\n",
778			vin->format.pixelformat);
779		return -EINVAL;
780	}
781
782	/* Always update on field change */
783	vnmc |= VNMC_VUP;
784
785	/* If input and output use the same colorspace, use bypass mode */
786	if (input_is_yuv == output_is_yuv)
787		vnmc |= VNMC_BPS;
788
789	if (vin->info->model == RCAR_GEN3) {
790		/* Select between CSI-2 and parallel input */
791		if (vin->is_csi)
792			vnmc &= ~VNMC_DPINE;
793		else
794			vnmc |= VNMC_DPINE;
795	}
796
797	/* Progressive or interlaced mode */
798	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
799
800	/* Ack interrupts */
801	rvin_write(vin, interrupts, VNINTS_REG);
802	/* Enable interrupts */
803	rvin_write(vin, interrupts, VNIE_REG);
804	/* Start capturing */
805	rvin_write(vin, dmr, VNDMR_REG);
806	rvin_write(vin, dmr2, VNDMR2_REG);
807
808	/* Enable module */
809	rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
810
811	return 0;
812}
813
814static void rvin_disable_interrupts(struct rvin_dev *vin)
815{
816	rvin_write(vin, 0, VNIE_REG);
817}
818
819static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
820{
821	return rvin_read(vin, VNINTS_REG);
822}
823
824static void rvin_ack_interrupt(struct rvin_dev *vin)
825{
826	rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
827}
828
829static bool rvin_capture_active(struct rvin_dev *vin)
830{
831	return rvin_read(vin, VNMS_REG) & VNMS_CA;
832}
833
834static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
835{
836	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
837		/* If FS is set it is an Even field. */
838		if (vnms & VNMS_FS)
839			return V4L2_FIELD_BOTTOM;
840		return V4L2_FIELD_TOP;
841	}
842
843	return vin->format.field;
844}
845
846static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
847{
848	const struct rvin_video_format *fmt;
849	int offsetx, offsety;
850	dma_addr_t offset;
851
852	fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
853
854	/*
855	 * There is no HW support for composition do the beast we can
856	 * by modifying the buffer offset
857	 */
858	offsetx = vin->compose.left * fmt->bpp;
859	offsety = vin->compose.top * vin->format.bytesperline;
860	offset = addr + offsetx + offsety;
861
862	/*
863	 * The address needs to be 128 bytes aligned. Driver should never accept
864	 * settings that do not satisfy this in the first place...
865	 */
866	if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
867		return;
868
869	rvin_write(vin, offset, VNMB_REG(slot));
870}
871
872/*
873 * Moves a buffer from the queue to the HW slot. If no buffer is
874 * available use the scratch buffer. The scratch buffer is never
875 * returned to userspace, its only function is to enable the capture
876 * loop to keep running.
877 */
878static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
879{
880	struct rvin_buffer *buf;
881	struct vb2_v4l2_buffer *vbuf;
882	dma_addr_t phys_addr;
883	int prev;
884
885	/* A already populated slot shall never be overwritten. */
886	if (WARN_ON(vin->buf_hw[slot].buffer))
887		return;
888
889	prev = (slot == 0 ? HW_BUFFER_NUM : slot) - 1;
890
891	if (vin->buf_hw[prev].type == HALF_TOP) {
892		vbuf = vin->buf_hw[prev].buffer;
893		vin->buf_hw[slot].buffer = vbuf;
894		vin->buf_hw[slot].type = HALF_BOTTOM;
895		switch (vin->format.pixelformat) {
896		case V4L2_PIX_FMT_NV12:
897		case V4L2_PIX_FMT_NV16:
898			phys_addr = vin->buf_hw[prev].phys +
899				vin->format.sizeimage / 4;
900			break;
901		default:
902			phys_addr = vin->buf_hw[prev].phys +
903				vin->format.sizeimage / 2;
904			break;
905		}
906	} else if (list_empty(&vin->buf_list)) {
907		vin->buf_hw[slot].buffer = NULL;
908		vin->buf_hw[slot].type = FULL;
909		phys_addr = vin->scratch_phys;
910	} else {
911		/* Keep track of buffer we give to HW */
912		buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
913		vbuf = &buf->vb;
914		list_del_init(to_buf_list(vbuf));
915		vin->buf_hw[slot].buffer = vbuf;
916
917		vin->buf_hw[slot].type =
918			V4L2_FIELD_IS_SEQUENTIAL(vin->format.field) ?
919			HALF_TOP : FULL;
920
921		/* Setup DMA */
922		phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
923	}
924
925	vin_dbg(vin, "Filling HW slot: %d type: %d buffer: %p\n",
926		slot, vin->buf_hw[slot].type, vin->buf_hw[slot].buffer);
927
928	vin->buf_hw[slot].phys = phys_addr;
929	rvin_set_slot_addr(vin, slot, phys_addr);
930}
931
932static int rvin_capture_start(struct rvin_dev *vin)
933{
934	int slot, ret;
935
936	for (slot = 0; slot < HW_BUFFER_NUM; slot++) {
937		vin->buf_hw[slot].buffer = NULL;
938		vin->buf_hw[slot].type = FULL;
939	}
940
941	for (slot = 0; slot < HW_BUFFER_NUM; slot++)
942		rvin_fill_hw_slot(vin, slot);
943
944	rvin_crop_scale_comp(vin);
945
946	ret = rvin_setup(vin);
947	if (ret)
948		return ret;
949
950	vin_dbg(vin, "Starting to capture\n");
951
952	/* Continuous Frame Capture Mode */
953	rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
954
955	vin->state = STARTING;
956
957	return 0;
958}
959
960static void rvin_capture_stop(struct rvin_dev *vin)
961{
962	/* Set continuous & single transfer off */
963	rvin_write(vin, 0, VNFC_REG);
964
965	/* Disable module */
966	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
967}
968
969/* -----------------------------------------------------------------------------
970 * DMA Functions
971 */
972
973#define RVIN_TIMEOUT_MS 100
974#define RVIN_RETRIES 10
975
976static irqreturn_t rvin_irq(int irq, void *data)
977{
978	struct rvin_dev *vin = data;
979	u32 int_status, vnms;
980	int slot;
981	unsigned int handled = 0;
982	unsigned long flags;
983
984	spin_lock_irqsave(&vin->qlock, flags);
985
986	int_status = rvin_get_interrupt_status(vin);
987	if (!int_status)
988		goto done;
989
990	rvin_ack_interrupt(vin);
991	handled = 1;
992
993	/* Nothing to do if capture status is 'STOPPED' */
994	if (vin->state == STOPPED) {
995		vin_dbg(vin, "IRQ while state stopped\n");
996		goto done;
997	}
998
999	/* Nothing to do if capture status is 'STOPPING' */
1000	if (vin->state == STOPPING) {
1001		vin_dbg(vin, "IRQ while state stopping\n");
1002		goto done;
1003	}
1004
1005	/* Prepare for capture and update state */
1006	vnms = rvin_read(vin, VNMS_REG);
1007	slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
1008
1009	/*
1010	 * To hand buffers back in a known order to userspace start
1011	 * to capture first from slot 0.
1012	 */
1013	if (vin->state == STARTING) {
1014		if (slot != 0) {
1015			vin_dbg(vin, "Starting sync slot: %d\n", slot);
1016			goto done;
1017		}
1018
1019		vin_dbg(vin, "Capture start synced!\n");
1020		vin->state = RUNNING;
1021	}
1022
1023	/* Capture frame */
1024	if (vin->buf_hw[slot].buffer) {
1025		/*
1026		 * Nothing to do but refill the hardware slot if
1027		 * capture only filled first half of vb2 buffer.
1028		 */
1029		if (vin->buf_hw[slot].type == HALF_TOP) {
1030			vin->buf_hw[slot].buffer = NULL;
1031			rvin_fill_hw_slot(vin, slot);
1032			goto done;
1033		}
1034
1035		vin->buf_hw[slot].buffer->field =
1036			rvin_get_active_field(vin, vnms);
1037		vin->buf_hw[slot].buffer->sequence = vin->sequence;
1038		vin->buf_hw[slot].buffer->vb2_buf.timestamp = ktime_get_ns();
1039		vb2_buffer_done(&vin->buf_hw[slot].buffer->vb2_buf,
1040				VB2_BUF_STATE_DONE);
1041		vin->buf_hw[slot].buffer = NULL;
1042	} else {
1043		/* Scratch buffer was used, dropping frame. */
1044		vin_dbg(vin, "Dropping frame %u\n", vin->sequence);
1045	}
1046
1047	vin->sequence++;
1048
1049	/* Prepare for next frame */
1050	rvin_fill_hw_slot(vin, slot);
1051done:
1052	spin_unlock_irqrestore(&vin->qlock, flags);
1053
1054	return IRQ_RETVAL(handled);
1055}
1056
1057/* Need to hold qlock before calling */
1058static void return_all_buffers(struct rvin_dev *vin,
1059			       enum vb2_buffer_state state)
1060{
1061	struct rvin_buffer *buf, *node;
1062	struct vb2_v4l2_buffer *freed[HW_BUFFER_NUM];
1063	unsigned int i, n;
1064
1065	for (i = 0; i < HW_BUFFER_NUM; i++) {
1066		freed[i] = vin->buf_hw[i].buffer;
1067		vin->buf_hw[i].buffer = NULL;
1068
1069		for (n = 0; n < i; n++) {
1070			if (freed[i] == freed[n]) {
1071				freed[i] = NULL;
1072				break;
1073			}
1074		}
1075
1076		if (freed[i])
1077			vb2_buffer_done(&freed[i]->vb2_buf, state);
1078	}
1079
1080	list_for_each_entry_safe(buf, node, &vin->buf_list, list) {
1081		vb2_buffer_done(&buf->vb.vb2_buf, state);
1082		list_del(&buf->list);
1083	}
1084}
1085
1086static int rvin_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1087			    unsigned int *nplanes, unsigned int sizes[],
1088			    struct device *alloc_devs[])
1089
1090{
1091	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1092
1093	/* Make sure the image size is large enough. */
1094	if (*nplanes)
1095		return sizes[0] < vin->format.sizeimage ? -EINVAL : 0;
1096
1097	*nplanes = 1;
1098	sizes[0] = vin->format.sizeimage;
1099
1100	return 0;
1101};
1102
1103static int rvin_buffer_prepare(struct vb2_buffer *vb)
1104{
1105	struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1106	unsigned long size = vin->format.sizeimage;
1107
1108	if (vb2_plane_size(vb, 0) < size) {
1109		vin_err(vin, "buffer too small (%lu < %lu)\n",
1110			vb2_plane_size(vb, 0), size);
1111		return -EINVAL;
1112	}
1113
1114	vb2_set_plane_payload(vb, 0, size);
1115
1116	return 0;
1117}
1118
1119static void rvin_buffer_queue(struct vb2_buffer *vb)
1120{
1121	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1122	struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1123	unsigned long flags;
1124
1125	spin_lock_irqsave(&vin->qlock, flags);
1126
1127	list_add_tail(to_buf_list(vbuf), &vin->buf_list);
1128
1129	spin_unlock_irqrestore(&vin->qlock, flags);
1130}
1131
1132static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
1133				   struct media_pad *pad)
1134{
1135	struct v4l2_subdev_format fmt = {
1136		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
1137	};
1138
1139	fmt.pad = pad->index;
1140	if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt))
1141		return -EPIPE;
1142
1143	switch (fmt.format.code) {
1144	case MEDIA_BUS_FMT_YUYV8_1X16:
1145	case MEDIA_BUS_FMT_UYVY8_1X16:
1146	case MEDIA_BUS_FMT_UYVY8_2X8:
1147	case MEDIA_BUS_FMT_UYVY10_2X10:
1148	case MEDIA_BUS_FMT_RGB888_1X24:
1149		break;
1150	case MEDIA_BUS_FMT_SBGGR8_1X8:
1151		if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR8)
1152			return -EPIPE;
1153		break;
1154	case MEDIA_BUS_FMT_SGBRG8_1X8:
1155		if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG8)
1156			return -EPIPE;
1157		break;
1158	case MEDIA_BUS_FMT_SGRBG8_1X8:
1159		if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG8)
1160			return -EPIPE;
1161		break;
1162	case MEDIA_BUS_FMT_SRGGB8_1X8:
1163		if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB8)
1164			return -EPIPE;
1165		break;
1166	default:
1167		return -EPIPE;
1168	}
1169	vin->mbus_code = fmt.format.code;
1170
1171	switch (fmt.format.field) {
1172	case V4L2_FIELD_TOP:
1173	case V4L2_FIELD_BOTTOM:
1174	case V4L2_FIELD_NONE:
1175	case V4L2_FIELD_INTERLACED_TB:
1176	case V4L2_FIELD_INTERLACED_BT:
1177	case V4L2_FIELD_INTERLACED:
1178	case V4L2_FIELD_SEQ_TB:
1179	case V4L2_FIELD_SEQ_BT:
1180		/* Supported natively */
1181		break;
1182	case V4L2_FIELD_ALTERNATE:
1183		switch (vin->format.field) {
1184		case V4L2_FIELD_TOP:
1185		case V4L2_FIELD_BOTTOM:
1186		case V4L2_FIELD_NONE:
1187		case V4L2_FIELD_ALTERNATE:
1188			break;
1189		case V4L2_FIELD_INTERLACED_TB:
1190		case V4L2_FIELD_INTERLACED_BT:
1191		case V4L2_FIELD_INTERLACED:
1192		case V4L2_FIELD_SEQ_TB:
1193		case V4L2_FIELD_SEQ_BT:
1194			/* Use VIN hardware to combine the two fields */
1195			fmt.format.height *= 2;
1196			break;
1197		default:
1198			return -EPIPE;
1199		}
1200		break;
1201	default:
1202		return -EPIPE;
1203	}
1204
1205	if (fmt.format.width != vin->format.width ||
1206	    fmt.format.height != vin->format.height ||
1207	    fmt.format.code != vin->mbus_code)
1208		return -EPIPE;
1209
1210	return 0;
1211}
1212
1213static int rvin_set_stream(struct rvin_dev *vin, int on)
1214{
1215	struct media_pipeline *pipe;
1216	struct media_device *mdev;
1217	struct v4l2_subdev *sd;
1218	struct media_pad *pad;
1219	int ret;
1220
1221	/* No media controller used, simply pass operation to subdevice. */
1222	if (!vin->info->use_mc) {
1223		ret = v4l2_subdev_call(vin->parallel->subdev, video, s_stream,
1224				       on);
1225
1226		return ret == -ENOIOCTLCMD ? 0 : ret;
1227	}
1228
1229	pad = media_entity_remote_pad(&vin->pad);
1230	if (!pad)
1231		return -EPIPE;
1232
1233	sd = media_entity_to_v4l2_subdev(pad->entity);
1234
1235	if (!on) {
1236		media_pipeline_stop(&vin->vdev.entity);
1237		return v4l2_subdev_call(sd, video, s_stream, 0);
1238	}
1239
1240	ret = rvin_mc_validate_format(vin, sd, pad);
1241	if (ret)
1242		return ret;
1243
1244	/*
1245	 * The graph lock needs to be taken to protect concurrent
1246	 * starts of multiple VIN instances as they might share
1247	 * a common subdevice down the line and then should use
1248	 * the same pipe.
1249	 */
1250	mdev = vin->vdev.entity.graph_obj.mdev;
1251	mutex_lock(&mdev->graph_mutex);
1252	pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe;
1253	ret = __media_pipeline_start(&vin->vdev.entity, pipe);
1254	mutex_unlock(&mdev->graph_mutex);
1255	if (ret)
1256		return ret;
1257
1258	ret = v4l2_subdev_call(sd, video, s_stream, 1);
1259	if (ret == -ENOIOCTLCMD)
1260		ret = 0;
1261	if (ret)
1262		media_pipeline_stop(&vin->vdev.entity);
1263
1264	return ret;
1265}
1266
1267static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
1268{
1269	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1270	unsigned long flags;
1271	int ret;
1272
1273	/* Allocate scratch buffer. */
1274	vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
1275					  &vin->scratch_phys, GFP_KERNEL);
1276	if (!vin->scratch) {
1277		spin_lock_irqsave(&vin->qlock, flags);
1278		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
1279		spin_unlock_irqrestore(&vin->qlock, flags);
1280		vin_err(vin, "Failed to allocate scratch buffer\n");
1281		return -ENOMEM;
1282	}
1283
1284	ret = rvin_set_stream(vin, 1);
1285	if (ret) {
1286		spin_lock_irqsave(&vin->qlock, flags);
1287		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
1288		spin_unlock_irqrestore(&vin->qlock, flags);
1289		goto out;
1290	}
1291
1292	spin_lock_irqsave(&vin->qlock, flags);
1293
1294	vin->sequence = 0;
1295
1296	ret = rvin_capture_start(vin);
1297	if (ret) {
1298		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
1299		rvin_set_stream(vin, 0);
1300	}
1301
1302	spin_unlock_irqrestore(&vin->qlock, flags);
1303out:
1304	if (ret)
1305		dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1306				  vin->scratch_phys);
1307
1308	return ret;
1309}
1310
1311static void rvin_stop_streaming(struct vb2_queue *vq)
1312{
1313	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1314	unsigned long flags;
1315	int retries = 0;
1316
1317	spin_lock_irqsave(&vin->qlock, flags);
1318
1319	vin->state = STOPPING;
1320
1321	/* Wait for streaming to stop */
1322	while (retries++ < RVIN_RETRIES) {
1323
1324		rvin_capture_stop(vin);
1325
1326		/* Check if HW is stopped */
1327		if (!rvin_capture_active(vin)) {
1328			vin->state = STOPPED;
1329			break;
1330		}
1331
1332		spin_unlock_irqrestore(&vin->qlock, flags);
1333		msleep(RVIN_TIMEOUT_MS);
1334		spin_lock_irqsave(&vin->qlock, flags);
1335	}
1336
1337	if (vin->state != STOPPED) {
1338		/*
1339		 * If this happens something have gone horribly wrong.
1340		 * Set state to stopped to prevent the interrupt handler
1341		 * to make things worse...
1342		 */
1343		vin_err(vin, "Failed stop HW, something is seriously broken\n");
1344		vin->state = STOPPED;
1345	}
1346
1347	/* Release all active buffers */
1348	return_all_buffers(vin, VB2_BUF_STATE_ERROR);
1349
1350	spin_unlock_irqrestore(&vin->qlock, flags);
1351
1352	rvin_set_stream(vin, 0);
1353
1354	/* disable interrupts */
1355	rvin_disable_interrupts(vin);
1356
1357	/* Free scratch buffer. */
1358	dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1359			  vin->scratch_phys);
1360}
1361
1362static const struct vb2_ops rvin_qops = {
1363	.queue_setup		= rvin_queue_setup,
1364	.buf_prepare		= rvin_buffer_prepare,
1365	.buf_queue		= rvin_buffer_queue,
1366	.start_streaming	= rvin_start_streaming,
1367	.stop_streaming		= rvin_stop_streaming,
1368	.wait_prepare		= vb2_ops_wait_prepare,
1369	.wait_finish		= vb2_ops_wait_finish,
1370};
1371
1372void rvin_dma_unregister(struct rvin_dev *vin)
1373{
1374	mutex_destroy(&vin->lock);
1375
1376	v4l2_device_unregister(&vin->v4l2_dev);
1377}
1378
1379int rvin_dma_register(struct rvin_dev *vin, int irq)
1380{
1381	struct vb2_queue *q = &vin->queue;
1382	int i, ret;
1383
1384	/* Initialize the top-level structure */
1385	ret = v4l2_device_register(vin->dev, &vin->v4l2_dev);
1386	if (ret)
1387		return ret;
1388
1389	mutex_init(&vin->lock);
1390	INIT_LIST_HEAD(&vin->buf_list);
1391
1392	spin_lock_init(&vin->qlock);
1393
1394	vin->state = STOPPED;
1395
1396	for (i = 0; i < HW_BUFFER_NUM; i++)
1397		vin->buf_hw[i].buffer = NULL;
1398
1399	/* buffer queue */
1400	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1401	q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1402	q->lock = &vin->lock;
1403	q->drv_priv = vin;
1404	q->buf_struct_size = sizeof(struct rvin_buffer);
1405	q->ops = &rvin_qops;
1406	q->mem_ops = &vb2_dma_contig_memops;
1407	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1408	q->min_buffers_needed = 4;
1409	q->dev = vin->dev;
1410
1411	ret = vb2_queue_init(q);
1412	if (ret < 0) {
1413		vin_err(vin, "failed to initialize VB2 queue\n");
1414		goto error;
1415	}
1416
1417	/* irq */
1418	ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED,
1419			       KBUILD_MODNAME, vin);
1420	if (ret) {
1421		vin_err(vin, "failed to request irq\n");
1422		goto error;
1423	}
1424
1425	return 0;
1426error:
1427	rvin_dma_unregister(vin);
1428
1429	return ret;
1430}
1431
1432/* -----------------------------------------------------------------------------
1433 * Gen3 CHSEL manipulation
1434 */
1435
1436/*
1437 * There is no need to have locking around changing the routing
1438 * as it's only possible to do so when no VIN in the group is
1439 * streaming so nothing can race with the VNMC register.
1440 */
1441int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
1442{
1443	u32 ifmd, vnmc;
1444	int ret;
1445
1446	ret = pm_runtime_get_sync(vin->dev);
1447	if (ret < 0) {
1448		pm_runtime_put_noidle(vin->dev);
1449		return ret;
1450	}
1451
1452	/* Make register writes take effect immediately. */
1453	vnmc = rvin_read(vin, VNMC_REG);
1454	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
1455
1456	ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 | VNCSI_IFMD_CSI_CHSEL(chsel);
1457
1458	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
1459
1460	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
1461
1462	/* Restore VNMC. */
1463	rvin_write(vin, vnmc, VNMC_REG);
1464
1465	pm_runtime_put(vin->dev);
1466
1467	return 0;
1468}
1469
1470void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha)
1471{
1472	unsigned long flags;
1473	u32 dmr;
1474
1475	spin_lock_irqsave(&vin->qlock, flags);
1476
1477	vin->alpha = alpha;
1478
1479	if (vin->state == STOPPED)
1480		goto out;
1481
1482	switch (vin->format.pixelformat) {
1483	case V4L2_PIX_FMT_ARGB555:
1484		dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT;
1485		if (vin->alpha)
1486			dmr |= VNDMR_ABIT;
1487		break;
1488	case V4L2_PIX_FMT_ABGR32:
1489		dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK;
1490		dmr |= VNDMR_A8BIT(vin->alpha);
1491		break;
1492	default:
1493		goto out;
1494	}
1495
1496	rvin_write(vin, dmr,  VNDMR_REG);
1497out:
1498	spin_unlock_irqrestore(&vin->qlock, flags);
1499}
1500