xref: /linux/drivers/media/platform/renesas/rcar-vin/rcar-dma.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1aa7b8278SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+
2f00add96SNiklas Söderlund /*
3f00add96SNiklas Söderlund  * Driver for Renesas R-Car VIN
4f00add96SNiklas Söderlund  *
5f00add96SNiklas Söderlund  * Copyright (C) 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
6f00add96SNiklas Söderlund  * Copyright (C) 2016 Renesas Electronics Corp.
7f00add96SNiklas Söderlund  * Copyright (C) 2011-2013 Renesas Solutions Corp.
8f00add96SNiklas Söderlund  * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
9f00add96SNiklas Söderlund  * Copyright (C) 2008 Magnus Damm
10f00add96SNiklas Söderlund  */
11f00add96SNiklas Söderlund 
12f00add96SNiklas Söderlund #include <linux/delay.h>
13f00add96SNiklas Söderlund #include <linux/interrupt.h>
14f00add96SNiklas Söderlund #include <linux/pm_runtime.h>
1590dedce9SNiklas Söderlund 
16f00add96SNiklas Söderlund #include <media/v4l2-event.h>
17f00add96SNiklas Söderlund #include <media/videobuf2-dma-contig.h>
18f00add96SNiklas Söderlund 
19f00add96SNiklas Söderlund #include "rcar-vin.h"
20f00add96SNiklas Söderlund 
21f00add96SNiklas Söderlund /* -----------------------------------------------------------------------------
22f00add96SNiklas Söderlund  * HW Functions
23f00add96SNiklas Söderlund  */
24f00add96SNiklas Söderlund 
25f00add96SNiklas Söderlund /* Register offsets for R-Car VIN */
26f00add96SNiklas Söderlund #define VNMC_REG	0x00	/* Video n Main Control Register */
27f00add96SNiklas Söderlund #define VNMS_REG	0x04	/* Video n Module Status Register */
28f00add96SNiklas Söderlund #define VNFC_REG	0x08	/* Video n Frame Capture Register */
29f00add96SNiklas Söderlund #define VNSLPRC_REG	0x0C	/* Video n Start Line Pre-Clip Register */
30f00add96SNiklas Söderlund #define VNELPRC_REG	0x10	/* Video n End Line Pre-Clip Register */
31f00add96SNiklas Söderlund #define VNSPPRC_REG	0x14	/* Video n Start Pixel Pre-Clip Register */
32f00add96SNiklas Söderlund #define VNEPPRC_REG	0x18	/* Video n End Pixel Pre-Clip Register */
33f00add96SNiklas Söderlund #define VNIS_REG	0x2C	/* Video n Image Stride Register */
34f00add96SNiklas Söderlund #define VNMB_REG(m)	(0x30 + ((m) << 2)) /* Video n Memory Base m Register */
35f00add96SNiklas Söderlund #define VNIE_REG	0x40	/* Video n Interrupt Enable Register */
36f00add96SNiklas Söderlund #define VNINTS_REG	0x44	/* Video n Interrupt Status Register */
37f00add96SNiklas Söderlund #define VNSI_REG	0x48	/* Video n Scanline Interrupt Register */
38f00add96SNiklas Söderlund #define VNMTC_REG	0x4C	/* Video n Memory Transfer Control Register */
39f00add96SNiklas Söderlund #define VNDMR_REG	0x58	/* Video n Data Mode Register */
40f00add96SNiklas Söderlund #define VNDMR2_REG	0x5C	/* Video n Data Mode Register 2 */
41f00add96SNiklas Söderlund #define VNUVAOF_REG	0x60	/* Video n UV Address Offset Register */
424394eb24SNiklas Söderlund 
434394eb24SNiklas Söderlund /* Register offsets specific for Gen2 */
444394eb24SNiklas Söderlund #define VNSLPOC_REG	0x1C	/* Video n Start Line Post-Clip Register */
454394eb24SNiklas Söderlund #define VNELPOC_REG	0x20	/* Video n End Line Post-Clip Register */
464394eb24SNiklas Söderlund #define VNSPPOC_REG	0x24	/* Video n Start Pixel Post-Clip Register */
474394eb24SNiklas Söderlund #define VNEPPOC_REG	0x28	/* Video n End Pixel Post-Clip Register */
484394eb24SNiklas Söderlund #define VNYS_REG	0x50	/* Video n Y Scale Register */
494394eb24SNiklas Söderlund #define VNXS_REG	0x54	/* Video n X Scale Register */
50f00add96SNiklas Söderlund #define VNC1A_REG	0x80	/* Video n Coefficient Set C1A Register */
51f00add96SNiklas Söderlund #define VNC1B_REG	0x84	/* Video n Coefficient Set C1B Register */
52f00add96SNiklas Söderlund #define VNC1C_REG	0x88	/* Video n Coefficient Set C1C Register */
53f00add96SNiklas Söderlund #define VNC2A_REG	0x90	/* Video n Coefficient Set C2A Register */
54f00add96SNiklas Söderlund #define VNC2B_REG	0x94	/* Video n Coefficient Set C2B Register */
55f00add96SNiklas Söderlund #define VNC2C_REG	0x98	/* Video n Coefficient Set C2C Register */
56f00add96SNiklas Söderlund #define VNC3A_REG	0xA0	/* Video n Coefficient Set C3A Register */
57f00add96SNiklas Söderlund #define VNC3B_REG	0xA4	/* Video n Coefficient Set C3B Register */
58f00add96SNiklas Söderlund #define VNC3C_REG	0xA8	/* Video n Coefficient Set C3C Register */
59f00add96SNiklas Söderlund #define VNC4A_REG	0xB0	/* Video n Coefficient Set C4A Register */
60f00add96SNiklas Söderlund #define VNC4B_REG	0xB4	/* Video n Coefficient Set C4B Register */
61f00add96SNiklas Söderlund #define VNC4C_REG	0xB8	/* Video n Coefficient Set C4C Register */
62f00add96SNiklas Söderlund #define VNC5A_REG	0xC0	/* Video n Coefficient Set C5A Register */
63f00add96SNiklas Söderlund #define VNC5B_REG	0xC4	/* Video n Coefficient Set C5B Register */
64f00add96SNiklas Söderlund #define VNC5C_REG	0xC8	/* Video n Coefficient Set C5C Register */
65f00add96SNiklas Söderlund #define VNC6A_REG	0xD0	/* Video n Coefficient Set C6A Register */
66f00add96SNiklas Söderlund #define VNC6B_REG	0xD4	/* Video n Coefficient Set C6B Register */
67f00add96SNiklas Söderlund #define VNC6C_REG	0xD8	/* Video n Coefficient Set C6C Register */
68f00add96SNiklas Söderlund #define VNC7A_REG	0xE0	/* Video n Coefficient Set C7A Register */
69f00add96SNiklas Söderlund #define VNC7B_REG	0xE4	/* Video n Coefficient Set C7B Register */
70f00add96SNiklas Söderlund #define VNC7C_REG	0xE8	/* Video n Coefficient Set C7C Register */
71f00add96SNiklas Söderlund #define VNC8A_REG	0xF0	/* Video n Coefficient Set C8A Register */
72f00add96SNiklas Söderlund #define VNC8B_REG	0xF4	/* Video n Coefficient Set C8B Register */
73f00add96SNiklas Söderlund #define VNC8C_REG	0xF8	/* Video n Coefficient Set C8C Register */
74f00add96SNiklas Söderlund 
754394eb24SNiklas Söderlund /* Register offsets specific for Gen3 */
764394eb24SNiklas Söderlund #define VNCSI_IFMD_REG		0x20 /* Video n CSI2 Interface Mode Register */
77928a6ea4SNiklas Söderlund #define VNUDS_CTRL_REG		0x80 /* Video n scaling control register */
78928a6ea4SNiklas Söderlund #define VNUDS_SCALE_REG		0x84 /* Video n scaling factor register */
79928a6ea4SNiklas Söderlund #define VNUDS_PASS_BWIDTH_REG	0x90 /* Video n passband register */
80928a6ea4SNiklas Söderlund #define VNUDS_CLIP_SIZE_REG	0xa4 /* Video n UDS output size clipping reg */
81f00add96SNiklas Söderlund 
82f00add96SNiklas Söderlund /* Register bit fields for R-Car VIN */
83f00add96SNiklas Söderlund /* Video n Main Control Register bits */
8478b3f9d7SNiklas Söderlund #define VNMC_INF_MASK		(7 << 16)
854394eb24SNiklas Söderlund #define VNMC_DPINE		(1 << 27) /* Gen3 specific */
864394eb24SNiklas Söderlund #define VNMC_SCLE		(1 << 26) /* Gen3 specific */
87f00add96SNiklas Söderlund #define VNMC_FOC		(1 << 21)
88f00add96SNiklas Söderlund #define VNMC_YCAL		(1 << 19)
89f00add96SNiklas Söderlund #define VNMC_INF_YUV8_BT656	(0 << 16)
90f00add96SNiklas Söderlund #define VNMC_INF_YUV8_BT601	(1 << 16)
91f00add96SNiklas Söderlund #define VNMC_INF_YUV10_BT656	(2 << 16)
92f00add96SNiklas Söderlund #define VNMC_INF_YUV10_BT601	(3 << 16)
93e87c1a81SLad Prabhakar #define VNMC_INF_RAW8		(4 << 16)
94f00add96SNiklas Söderlund #define VNMC_INF_YUV16		(5 << 16)
95f00add96SNiklas Söderlund #define VNMC_INF_RGB888		(6 << 16)
9678b3f9d7SNiklas Söderlund #define VNMC_INF_RGB666		(7 << 16)
9717b5496cSTomi Valkeinen #define VNMC_EXINF_RAW8		(1 << 12) /* Gen4 specific */
98f00add96SNiklas Söderlund #define VNMC_VUP		(1 << 10)
99f00add96SNiklas Söderlund #define VNMC_IM_ODD		(0 << 3)
100f00add96SNiklas Söderlund #define VNMC_IM_ODD_EVEN	(1 << 3)
101f00add96SNiklas Söderlund #define VNMC_IM_EVEN		(2 << 3)
102f00add96SNiklas Söderlund #define VNMC_IM_FULL		(3 << 3)
103f00add96SNiklas Söderlund #define VNMC_BPS		(1 << 1)
104f00add96SNiklas Söderlund #define VNMC_ME			(1 << 0)
105f00add96SNiklas Söderlund 
106f00add96SNiklas Söderlund /* Video n Module Status Register bits */
107f00add96SNiklas Söderlund #define VNMS_FBS_MASK		(3 << 3)
108f00add96SNiklas Söderlund #define VNMS_FBS_SHIFT		3
109b6f556cbSNiklas Söderlund #define VNMS_FS			(1 << 2)
110f00add96SNiklas Söderlund #define VNMS_AV			(1 << 1)
111f00add96SNiklas Söderlund #define VNMS_CA			(1 << 0)
112f00add96SNiklas Söderlund 
113f00add96SNiklas Söderlund /* Video n Frame Capture Register bits */
114f00add96SNiklas Söderlund #define VNFC_C_FRAME		(1 << 1)
115f00add96SNiklas Söderlund #define VNFC_S_FRAME		(1 << 0)
116f00add96SNiklas Söderlund 
117f00add96SNiklas Söderlund /* Video n Interrupt Enable Register bits */
118f00add96SNiklas Söderlund #define VNIE_VFE		BIT(17)
119f00add96SNiklas Söderlund #define VNIE_VRE		BIT(16)
120f00add96SNiklas Söderlund #define VNIE_FIE		BIT(4)
12130334d3dSNiklas Söderlund #define VNIE_EFE		BIT(1)
12230334d3dSNiklas Söderlund 
12330334d3dSNiklas Söderlund /* Video n Interrupt Status Register bits */
124f00add96SNiklas Söderlund #define VNINTS_VFS		BIT(17)
1251d99e68cSNiklas Söderlund #define VNINTS_VRS		BIT(16)
1261d99e68cSNiklas Söderlund #define VNINTS_FIS		BIT(4)
1271b7e7240SNiklas Söderlund #define VNINTS_EFS		BIT(1)
128c93beb52SVladimir Barinov 
1291b7e7240SNiklas Söderlund /* Video n Data Mode Register bits */
130f00add96SNiklas Söderlund #define VNDMR_A8BIT(n)		(((n) & 0xff) << 24)
131f00add96SNiklas Söderlund #define VNDMR_A8BIT_MASK	(0xff << 24)
1321d99e68cSNiklas Söderlund #define VNDMR_RMODE_RAW10	(2 << 19)
133f00add96SNiklas Söderlund #define VNDMR_YMODE_Y8		(1 << 12)
13419ab1f64SNiklas Söderlund #define VNDMR_YC_THR		(1 << 11)
1359b744a3eSNiklas Söderlund #define VNDMR_EXRGB		(1 << 8)
136f00add96SNiklas Söderlund #define VNDMR_BPSM		(1 << 4)
137f00add96SNiklas Söderlund #define VNDMR_ABIT		(1 << 2)
138f00add96SNiklas Söderlund #define VNDMR_DTMD_YCSEP	(1 << 1)
139f00add96SNiklas Söderlund #define VNDMR_DTMD_ARGB		(1 << 0)
14053cf3100SJacopo Mondi #define VNDMR_DTMD_YCSEP_420	(3 << 0)
141e8834943SLad Prabhakar 
142f00add96SNiklas Söderlund /* Video n Data Mode Register 2 bits */
143f00add96SNiklas Söderlund #define VNDMR2_VPS		(1 << 30)
144f00add96SNiklas Söderlund #define VNDMR2_HPS		(1 << 29)
1454394eb24SNiklas Söderlund #define VNDMR2_CES		(1 << 28)
1464394eb24SNiklas Söderlund #define VNDMR2_YDS		(1 << 22)
1474394eb24SNiklas Söderlund #define VNDMR2_FTEV		(1 << 17)
1484394eb24SNiklas Söderlund #define VNDMR2_VLV(n)		((n & 0xf) << 12)
1494394eb24SNiklas Söderlund 
150928a6ea4SNiklas Söderlund /* Video n CSI2 Interface Mode Register (Gen3) */
151928a6ea4SNiklas Söderlund #define VNCSI_IFMD_DES1		(1 << 26)
152928a6ea4SNiklas Söderlund #define VNCSI_IFMD_DES0		(1 << 25)
1539e921447SNiklas Söderlund #define VNCSI_IFMD_CSI_CHSEL(n) (((n) & 0xf) << 0)
1549e921447SNiklas Söderlund 
1559e921447SNiklas Söderlund /* Video n scaling control register (Gen3) */
1569e921447SNiklas Söderlund #define VNUDS_CTRL_AMD		(1 << 30)
1579e921447SNiklas Söderlund 
1589e921447SNiklas Söderlund struct rvin_buffer {
1599e921447SNiklas Söderlund 	struct vb2_v4l2_buffer vb;
1609e921447SNiklas Söderlund 	struct list_head list;
1619e921447SNiklas Söderlund };
162f00add96SNiklas Söderlund 
163f00add96SNiklas Söderlund #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
164f00add96SNiklas Söderlund 					       struct rvin_buffer, \
165f00add96SNiklas Söderlund 					       vb)->list)
166f00add96SNiklas Söderlund 
rvin_write(struct rvin_dev * vin,u32 value,u32 offset)167f00add96SNiklas Söderlund static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
168f00add96SNiklas Söderlund {
169f00add96SNiklas Söderlund 	iowrite32(value, vin->base + offset);
170f00add96SNiklas Söderlund }
171f00add96SNiklas Söderlund 
rvin_read(struct rvin_dev * vin,u32 offset)172f00add96SNiklas Söderlund static u32 rvin_read(struct rvin_dev *vin, u32 offset)
1733ad69c61SNiklas Söderlund {
174f00add96SNiklas Söderlund 	return ioread32(vin->base + offset);
175f00add96SNiklas Söderlund }
1763ad69c61SNiklas Söderlund 
1773ad69c61SNiklas Söderlund /* -----------------------------------------------------------------------------
1783ad69c61SNiklas Söderlund  * Crop and Scaling
1793ad69c61SNiklas Söderlund  */
1803ad69c61SNiklas Söderlund 
rvin_scaler_needed(const struct rvin_dev * vin)1813ad69c61SNiklas Söderlund static bool rvin_scaler_needed(const struct rvin_dev *vin)
1823ad69c61SNiklas Söderlund {
1833ad69c61SNiklas Söderlund 	return !(vin->crop.width == vin->format.width &&
184f00add96SNiklas Söderlund 		 vin->compose.width == vin->format.width &&
185f00add96SNiklas Söderlund 		 vin->crop.height == vin->format.height &&
186f00add96SNiklas Söderlund 		 vin->compose.height == vin->format.height);
187f00add96SNiklas Söderlund }
188f00add96SNiklas Söderlund 
189f00add96SNiklas Söderlund struct vin_coeff {
190f00add96SNiklas Söderlund 	unsigned short xs_value;
191f00add96SNiklas Söderlund 	u32 coeff_set[24];
192f00add96SNiklas Söderlund };
193f00add96SNiklas Söderlund 
194f00add96SNiklas Söderlund static const struct vin_coeff vin_coeff_set[] = {
195f00add96SNiklas Söderlund 	{ 0x0000, {
196f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
197f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
198f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
199f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
200f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
201f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
202f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000,
203f00add96SNiklas Söderlund 			  0x00000000, 0x00000000, 0x00000000 },
204f00add96SNiklas Söderlund 	},
205f00add96SNiklas Söderlund 	{ 0x1000, {
206f00add96SNiklas Söderlund 			  0x000fa400, 0x000fa400, 0x09625902,
207f00add96SNiklas Söderlund 			  0x000003f8, 0x00000403, 0x3de0d9f0,
208f00add96SNiklas Söderlund 			  0x001fffed, 0x00000804, 0x3cc1f9c3,
209f00add96SNiklas Söderlund 			  0x001003de, 0x00000c01, 0x3cb34d7f,
210f00add96SNiklas Söderlund 			  0x002003d2, 0x00000c00, 0x3d24a92d,
211f00add96SNiklas Söderlund 			  0x00200bca, 0x00000bff, 0x3df600d2,
212f00add96SNiklas Söderlund 			  0x002013cc, 0x000007ff, 0x3ed70c7e,
213f00add96SNiklas Söderlund 			  0x00100fde, 0x00000000, 0x3f87c036 },
214f00add96SNiklas Söderlund 	},
215f00add96SNiklas Söderlund 	{ 0x1200, {
216f00add96SNiklas Söderlund 			  0x002ffff1, 0x002ffff1, 0x02a0a9c8,
217f00add96SNiklas Söderlund 			  0x002003e7, 0x001ffffa, 0x000185bc,
218f00add96SNiklas Söderlund 			  0x002007dc, 0x000003ff, 0x3e52859c,
219f00add96SNiklas Söderlund 			  0x00200bd4, 0x00000002, 0x3d53996b,
220f00add96SNiklas Söderlund 			  0x00100fd0, 0x00000403, 0x3d04ad2d,
221f00add96SNiklas Söderlund 			  0x00000bd5, 0x00000403, 0x3d35ace7,
222f00add96SNiklas Söderlund 			  0x3ff003e4, 0x00000801, 0x3dc674a1,
223f00add96SNiklas Söderlund 			  0x3fffe800, 0x00000800, 0x3e76f461 },
224f00add96SNiklas Söderlund 	},
225f00add96SNiklas Söderlund 	{ 0x1400, {
226f00add96SNiklas Söderlund 			  0x00100be3, 0x00100be3, 0x04d1359a,
227f00add96SNiklas Söderlund 			  0x00000fdb, 0x002003ed, 0x0211fd93,
228f00add96SNiklas Söderlund 			  0x00000fd6, 0x002003f4, 0x0002d97b,
229f00add96SNiklas Söderlund 			  0x000007d6, 0x002ffffb, 0x3e93b956,
230f00add96SNiklas Söderlund 			  0x3ff003da, 0x001003ff, 0x3db49926,
231f00add96SNiklas Söderlund 			  0x3fffefe9, 0x00100001, 0x3d655cee,
232f00add96SNiklas Söderlund 			  0x3fffd400, 0x00000003, 0x3d65f4b6,
233f00add96SNiklas Söderlund 			  0x000fb421, 0x00000402, 0x3dc6547e },
234f00add96SNiklas Söderlund 	},
235f00add96SNiklas Söderlund 	{ 0x1600, {
236f00add96SNiklas Söderlund 			  0x00000bdd, 0x00000bdd, 0x06519578,
237f00add96SNiklas Söderlund 			  0x3ff007da, 0x00000be3, 0x03c24973,
238f00add96SNiklas Söderlund 			  0x3ff003d9, 0x00000be9, 0x01b30d5f,
239f00add96SNiklas Söderlund 			  0x3ffff7df, 0x001003f1, 0x0003c542,
240f00add96SNiklas Söderlund 			  0x000fdfec, 0x001003f7, 0x3ec4711d,
241f00add96SNiklas Söderlund 			  0x000fc400, 0x002ffffd, 0x3df504f1,
242f00add96SNiklas Söderlund 			  0x001fa81a, 0x002ffc00, 0x3d957cc2,
243f00add96SNiklas Söderlund 			  0x002f8c3c, 0x00100000, 0x3db5c891 },
244f00add96SNiklas Söderlund 	},
245f00add96SNiklas Söderlund 	{ 0x1800, {
246f00add96SNiklas Söderlund 			  0x3ff003dc, 0x3ff003dc, 0x0791e558,
247f00add96SNiklas Söderlund 			  0x000ff7dd, 0x3ff007de, 0x05328554,
248f00add96SNiklas Söderlund 			  0x000fe7e3, 0x3ff00be2, 0x03232546,
249f00add96SNiklas Söderlund 			  0x000fd7ee, 0x000007e9, 0x0143bd30,
250f00add96SNiklas Söderlund 			  0x001fb800, 0x000007ee, 0x00044511,
251f00add96SNiklas Söderlund 			  0x002fa015, 0x000007f4, 0x3ef4bcee,
252f00add96SNiklas Söderlund 			  0x002f8832, 0x001003f9, 0x3e4514c7,
253f00add96SNiklas Söderlund 			  0x001f7853, 0x001003fd, 0x3de54c9f },
254f00add96SNiklas Söderlund 	},
255f00add96SNiklas Söderlund 	{ 0x1a00, {
256f00add96SNiklas Söderlund 			  0x000fefe0, 0x000fefe0, 0x08721d3c,
257f00add96SNiklas Söderlund 			  0x001fdbe7, 0x000ffbde, 0x0652a139,
258f00add96SNiklas Söderlund 			  0x001fcbf0, 0x000003df, 0x0463292e,
259f00add96SNiklas Söderlund 			  0x002fb3ff, 0x3ff007e3, 0x0293a91d,
260f00add96SNiklas Söderlund 			  0x002f9c12, 0x3ff00be7, 0x01241905,
261f00add96SNiklas Söderlund 			  0x001f8c29, 0x000007ed, 0x3fe470eb,
262f00add96SNiklas Söderlund 			  0x000f7c46, 0x000007f2, 0x3f04b8ca,
263f00add96SNiklas Söderlund 			  0x3fef7865, 0x000007f6, 0x3e74e4a8 },
264f00add96SNiklas Söderlund 	},
265f00add96SNiklas Söderlund 	{ 0x1c00, {
266f00add96SNiklas Söderlund 			  0x001fd3e9, 0x001fd3e9, 0x08f23d26,
267f00add96SNiklas Söderlund 			  0x002fbff3, 0x001fe3e4, 0x0712ad23,
268f00add96SNiklas Söderlund 			  0x002fa800, 0x000ff3e0, 0x05631d1b,
269f00add96SNiklas Söderlund 			  0x001f9810, 0x000ffbe1, 0x03b3890d,
270f00add96SNiklas Söderlund 			  0x000f8c23, 0x000003e3, 0x0233e8fa,
271f00add96SNiklas Söderlund 			  0x3fef843b, 0x000003e7, 0x00f430e4,
272f00add96SNiklas Söderlund 			  0x3fbf8456, 0x3ff00bea, 0x00046cc8,
273f00add96SNiklas Söderlund 			  0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
274f00add96SNiklas Söderlund 	},
275f00add96SNiklas Söderlund 	{ 0x1e00, {
276f00add96SNiklas Söderlund 			  0x001fbbf4, 0x001fbbf4, 0x09425112,
277f00add96SNiklas Söderlund 			  0x001fa800, 0x002fc7ed, 0x0792b110,
278f00add96SNiklas Söderlund 			  0x000f980e, 0x001fdbe6, 0x0613110a,
279f00add96SNiklas Söderlund 			  0x3fff8c20, 0x001fe7e3, 0x04a368fd,
280f00add96SNiklas Söderlund 			  0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
281f00add96SNiklas Söderlund 			  0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
282f00add96SNiklas Söderlund 			  0x3f5f9c61, 0x000003e6, 0x00e428c5,
283f00add96SNiklas Söderlund 			  0x3f1fb07b, 0x000003eb, 0x3fe440af },
284f00add96SNiklas Söderlund 	},
285f00add96SNiklas Söderlund 	{ 0x2000, {
286f00add96SNiklas Söderlund 			  0x000fa400, 0x000fa400, 0x09625902,
287f00add96SNiklas Söderlund 			  0x3fff980c, 0x001fb7f5, 0x0812b0ff,
288f00add96SNiklas Söderlund 			  0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
289f00add96SNiklas Söderlund 			  0x3faf902d, 0x001fd3e8, 0x055348f1,
290f00add96SNiklas Söderlund 			  0x3f7f983f, 0x001fe3e5, 0x04038ce3,
291f00add96SNiklas Söderlund 			  0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
292f00add96SNiklas Söderlund 			  0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
293f00add96SNiklas Söderlund 			  0x3ecfd880, 0x000fffe6, 0x00c404ac },
294f00add96SNiklas Söderlund 	},
295f00add96SNiklas Söderlund 	{ 0x2200, {
296f00add96SNiklas Söderlund 			  0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
297f00add96SNiklas Söderlund 			  0x3fbf9818, 0x3fffa400, 0x0842a8f1,
298f00add96SNiklas Söderlund 			  0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
299f00add96SNiklas Söderlund 			  0x3f5fa037, 0x000fc3ef, 0x05d330e4,
300f00add96SNiklas Söderlund 			  0x3f2fac49, 0x001fcfea, 0x04a364d9,
301f00add96SNiklas Söderlund 			  0x3effc05c, 0x001fdbe7, 0x038394ca,
302f00add96SNiklas Söderlund 			  0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
303f00add96SNiklas Söderlund 			  0x3ea00083, 0x001fefe6, 0x0183c0a9 },
304f00add96SNiklas Söderlund 	},
305f00add96SNiklas Söderlund 	{ 0x2400, {
306f00add96SNiklas Söderlund 			  0x3f9fa014, 0x3f9fa014, 0x098260e6,
307f00add96SNiklas Söderlund 			  0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
308f00add96SNiklas Söderlund 			  0x3f4fa431, 0x3fefa400, 0x0742d8e1,
309f00add96SNiklas Söderlund 			  0x3f1fb440, 0x3fffb3f8, 0x062310d9,
310f00add96SNiklas Söderlund 			  0x3eefc850, 0x000fbbf2, 0x050340d0,
311f00add96SNiklas Söderlund 			  0x3ecfe062, 0x000fcbec, 0x041364c2,
312f00add96SNiklas Söderlund 			  0x3ea00073, 0x001fd3ea, 0x03037cb5,
313f00add96SNiklas Söderlund 			  0x3e902086, 0x001fdfe8, 0x022388a5 },
314f00add96SNiklas Söderlund 	},
315f00add96SNiklas Söderlund 	{ 0x2600, {
316f00add96SNiklas Söderlund 			  0x3f5fa81e, 0x3f5fa81e, 0x096258da,
317f00add96SNiklas Söderlund 			  0x3f3fac2b, 0x3f8fa412, 0x088290d8,
318f00add96SNiklas Söderlund 			  0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
319f00add96SNiklas Söderlund 			  0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
320f00add96SNiklas Söderlund 			  0x3ecfe456, 0x3fefaffa, 0x05531cc6,
321f00add96SNiklas Söderlund 			  0x3eb00066, 0x3fffbbf3, 0x047334bb,
322f00add96SNiklas Söderlund 			  0x3ea01c77, 0x000fc7ee, 0x039348ae,
323f00add96SNiklas Söderlund 			  0x3ea04486, 0x000fd3eb, 0x02b350a1 },
324f00add96SNiklas Söderlund 	},
325f00add96SNiklas Söderlund 	{ 0x2800, {
326f00add96SNiklas Söderlund 			  0x3f2fb426, 0x3f2fb426, 0x094250ce,
327f00add96SNiklas Söderlund 			  0x3f0fc032, 0x3f4fac1b, 0x086284cd,
328f00add96SNiklas Söderlund 			  0x3eefd040, 0x3f7fa811, 0x0782acc9,
329f00add96SNiklas Söderlund 			  0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
330f00add96SNiklas Söderlund 			  0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
331f00add96SNiklas Söderlund 			  0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
332f00add96SNiklas Söderlund 			  0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
333f00add96SNiklas Söderlund 			  0x3ec06884, 0x000fbff2, 0x03031c9e },
334f00add96SNiklas Söderlund 	},
335f00add96SNiklas Söderlund 	{ 0x2a00, {
336f00add96SNiklas Söderlund 			  0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
337f00add96SNiklas Söderlund 			  0x3eefd439, 0x3f2fb822, 0x08526cc2,
338f00add96SNiklas Söderlund 			  0x3edfe845, 0x3f4fb018, 0x078294bf,
339f00add96SNiklas Söderlund 			  0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
340f00add96SNiklas Söderlund 			  0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
341f00add96SNiklas Söderlund 			  0x3ec0386b, 0x3fafac00, 0x0502e8ac,
342f00add96SNiklas Söderlund 			  0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
343f00add96SNiklas Söderlund 			  0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
344f00add96SNiklas Söderlund 	},
345f00add96SNiklas Söderlund 	{ 0x2c00, {
346f00add96SNiklas Söderlund 			  0x3eefdc31, 0x3eefdc31, 0x08e238b8,
347f00add96SNiklas Söderlund 			  0x3edfec3d, 0x3f0fc828, 0x082258b9,
348f00add96SNiklas Söderlund 			  0x3ed00049, 0x3f1fc01e, 0x077278b6,
349f00add96SNiklas Söderlund 			  0x3ed01455, 0x3f3fb815, 0x06c294b2,
350f00add96SNiklas Söderlund 			  0x3ed03460, 0x3f5fb40d, 0x0602acac,
351f00add96SNiklas Söderlund 			  0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
352f00add96SNiklas Söderlund 			  0x3f107476, 0x3f9fb400, 0x0472c89d,
353f00add96SNiklas Söderlund 			  0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
354f00add96SNiklas Söderlund 	},
355f00add96SNiklas Söderlund 	{ 0x2e00, {
356f00add96SNiklas Söderlund 			  0x3eefec37, 0x3eefec37, 0x088220b0,
357f00add96SNiklas Söderlund 			  0x3ee00041, 0x3effdc2d, 0x07f244ae,
358f00add96SNiklas Söderlund 			  0x3ee0144c, 0x3f0fd023, 0x07625cad,
359f00add96SNiklas Söderlund 			  0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
360f00add96SNiklas Söderlund 			  0x3f004861, 0x3f3fbc13, 0x060288a6,
361f00add96SNiklas Söderlund 			  0x3f20686b, 0x3f5fb80c, 0x05529c9e,
362f00add96SNiklas Söderlund 			  0x3f408c74, 0x3f6fb805, 0x04b2ac96,
363f00add96SNiklas Söderlund 			  0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
364f00add96SNiklas Söderlund 	},
365f00add96SNiklas Söderlund 	{ 0x3000, {
366f00add96SNiklas Söderlund 			  0x3ef0003a, 0x3ef0003a, 0x084210a6,
367f00add96SNiklas Söderlund 			  0x3ef01045, 0x3effec32, 0x07b228a7,
368f00add96SNiklas Söderlund 			  0x3f00284e, 0x3f0fdc29, 0x073244a4,
369f00add96SNiklas Söderlund 			  0x3f104058, 0x3f0fd420, 0x06a258a2,
370f00add96SNiklas Söderlund 			  0x3f305c62, 0x3f2fc818, 0x0612689d,
371f00add96SNiklas Söderlund 			  0x3f508069, 0x3f3fc011, 0x05728496,
372f00add96SNiklas Söderlund 			  0x3f80a072, 0x3f4fc00a, 0x04d28c90,
373f00add96SNiklas Söderlund 			  0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
374f00add96SNiklas Söderlund 	},
375f00add96SNiklas Söderlund 	{ 0x3200, {
376f00add96SNiklas Söderlund 			  0x3f00103e, 0x3f00103e, 0x07f1fc9e,
377f00add96SNiklas Söderlund 			  0x3f102447, 0x3f000035, 0x0782149d,
378f00add96SNiklas Söderlund 			  0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
379f00add96SNiklas Söderlund 			  0x3f405458, 0x3f0fe424, 0x06924099,
380f00add96SNiklas Söderlund 			  0x3f607061, 0x3f1fd41d, 0x06024c97,
381f00add96SNiklas Söderlund 			  0x3f909068, 0x3f2fcc16, 0x05726490,
382f00add96SNiklas Söderlund 			  0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
383f00add96SNiklas Söderlund 			  0x0000d077, 0x3f4fc409, 0x04627484 },
384f00add96SNiklas Söderlund 	},
385f00add96SNiklas Söderlund 	{ 0x3400, {
386f00add96SNiklas Söderlund 			  0x3f202040, 0x3f202040, 0x07a1e898,
387f00add96SNiklas Söderlund 			  0x3f303449, 0x3f100c38, 0x0741fc98,
388f00add96SNiklas Söderlund 			  0x3f504c50, 0x3f10002f, 0x06e21495,
389f00add96SNiklas Söderlund 			  0x3f706459, 0x3f1ff028, 0x06722492,
390f00add96SNiklas Söderlund 			  0x3fa08060, 0x3f1fe421, 0x05f2348f,
391f00add96SNiklas Söderlund 			  0x3fd09c67, 0x3f1fdc19, 0x05824c89,
392f00add96SNiklas Söderlund 			  0x0000bc6e, 0x3f2fd014, 0x04f25086,
393f00add96SNiklas Söderlund 			  0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
394f00add96SNiklas Söderlund 	},
395f00add96SNiklas Söderlund 	{ 0x3600, {
396f00add96SNiklas Söderlund 			  0x3f403042, 0x3f403042, 0x0761d890,
397f00add96SNiklas Söderlund 			  0x3f504848, 0x3f301c3b, 0x0701f090,
398f00add96SNiklas Söderlund 			  0x3f805c50, 0x3f200c33, 0x06a2008f,
399f00add96SNiklas Söderlund 			  0x3fa07458, 0x3f10002b, 0x06520c8d,
400f00add96SNiklas Söderlund 			  0x3fd0905e, 0x3f1ff424, 0x05e22089,
401f00add96SNiklas Söderlund 			  0x0000ac65, 0x3f1fe81d, 0x05823483,
402f00add96SNiklas Söderlund 			  0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
403f00add96SNiklas Söderlund 			  0x0080e871, 0x3f2fd412, 0x0482407c },
404f00add96SNiklas Söderlund 	},
405f00add96SNiklas Söderlund 	{ 0x3800, {
406f00add96SNiklas Söderlund 			  0x3f604043, 0x3f604043, 0x0721c88a,
407f00add96SNiklas Söderlund 			  0x3f80544a, 0x3f502c3c, 0x06d1d88a,
408f00add96SNiklas Söderlund 			  0x3fb06851, 0x3f301c35, 0x0681e889,
409f00add96SNiklas Söderlund 			  0x3fd08456, 0x3f30082f, 0x0611fc88,
410f00add96SNiklas Söderlund 			  0x00009c5d, 0x3f200027, 0x05d20884,
411f00add96SNiklas Söderlund 			  0x0030b863, 0x3f2ff421, 0x05621880,
412f00add96SNiklas Söderlund 			  0x0070d468, 0x3f2fe81b, 0x0502247c,
413f00add96SNiklas Söderlund 			  0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
414f00add96SNiklas Söderlund 	},
415f00add96SNiklas Söderlund 	{ 0x3a00, {
416f00add96SNiklas Söderlund 			  0x3f904c44, 0x3f904c44, 0x06e1b884,
417f00add96SNiklas Söderlund 			  0x3fb0604a, 0x3f70383e, 0x0691c885,
418f00add96SNiklas Söderlund 			  0x3fe07451, 0x3f502c36, 0x0661d483,
419f00add96SNiklas Söderlund 			  0x00009055, 0x3f401831, 0x0601ec81,
420f00add96SNiklas Söderlund 			  0x0030a85b, 0x3f300c2a, 0x05b1f480,
421f00add96SNiklas Söderlund 			  0x0070c061, 0x3f300024, 0x0562047a,
422f00add96SNiklas Söderlund 			  0x00b0d867, 0x3f3ff41e, 0x05020c77,
423f00add96SNiklas Söderlund 			  0x00f0f46b, 0x3f2fec19, 0x04a21474 },
424f00add96SNiklas Söderlund 	},
425f00add96SNiklas Söderlund 	{ 0x3c00, {
426f00add96SNiklas Söderlund 			  0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
427f00add96SNiklas Söderlund 			  0x3fe06c4b, 0x3f902c3f, 0x0681c081,
428f00add96SNiklas Söderlund 			  0x0000844f, 0x3f703838, 0x0631cc7d,
429f00add96SNiklas Söderlund 			  0x00309855, 0x3f602433, 0x05d1d47e,
430f00add96SNiklas Söderlund 			  0x0060b459, 0x3f50142e, 0x0581e47b,
431f00add96SNiklas Söderlund 			  0x00a0c85f, 0x3f400828, 0x0531f078,
432f00add96SNiklas Söderlund 			  0x00e0e064, 0x3f300021, 0x0501fc73,
433f00add96SNiklas Söderlund 			  0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
434f00add96SNiklas Söderlund 	},
435f00add96SNiklas Söderlund 	{ 0x3e00, {
436f00add96SNiklas Söderlund 			  0x3fe06444, 0x3fe06444, 0x0681a07a,
437f00add96SNiklas Söderlund 			  0x00007849, 0x3fc0503f, 0x0641b07a,
438f00add96SNiklas Söderlund 			  0x0020904d, 0x3fa0403a, 0x05f1c07a,
439f00add96SNiklas Söderlund 			  0x0060a453, 0x3f803034, 0x05c1c878,
440f00add96SNiklas Söderlund 			  0x0090b858, 0x3f70202f, 0x0571d477,
441f00add96SNiklas Söderlund 			  0x00d0d05d, 0x3f501829, 0x0531e073,
442f00add96SNiklas Söderlund 			  0x0110e462, 0x3f500825, 0x04e1e471,
443f00add96SNiklas Söderlund 			  0x01510065, 0x3f40001f, 0x04a1f06d },
444f00add96SNiklas Söderlund 	},
445f00add96SNiklas Söderlund 	{ 0x4000, {
446f00add96SNiklas Söderlund 			  0x00007044, 0x00007044, 0x06519476,
447f00add96SNiklas Söderlund 			  0x00208448, 0x3fe05c3f, 0x0621a476,
448f00add96SNiklas Söderlund 			  0x0050984d, 0x3fc04c3a, 0x05e1b075,
449f00add96SNiklas Söderlund 			  0x0080ac52, 0x3fa03c35, 0x05a1b875,
450f00add96SNiklas Söderlund 			  0x00c0c056, 0x3f803030, 0x0561c473,
451f00add96SNiklas Söderlund 			  0x0100d45b, 0x3f70202b, 0x0521d46f,
452f00add96SNiklas Söderlund 			  0x0140e860, 0x3f601427, 0x04d1d46e,
453f00add96SNiklas Söderlund 			  0x01810064, 0x3f500822, 0x0491dc6b },
454f00add96SNiklas Söderlund 	},
455f00add96SNiklas Söderlund 	{ 0x5000, {
456f00add96SNiklas Söderlund 			  0x0110a442, 0x0110a442, 0x0551545e,
457f00add96SNiklas Söderlund 			  0x0140b045, 0x00e0983f, 0x0531585f,
458f00add96SNiklas Söderlund 			  0x0160c047, 0x00c08c3c, 0x0511645e,
459f00add96SNiklas Söderlund 			  0x0190cc4a, 0x00908039, 0x04f1685f,
460f00add96SNiklas Söderlund 			  0x01c0dc4c, 0x00707436, 0x04d1705e,
461f00add96SNiklas Söderlund 			  0x0200e850, 0x00506833, 0x04b1785b,
462f00add96SNiklas Söderlund 			  0x0230f453, 0x00305c30, 0x0491805a,
463f00add96SNiklas Söderlund 			  0x02710056, 0x0010542d, 0x04718059 },
464f00add96SNiklas Söderlund 	},
465f00add96SNiklas Söderlund 	{ 0x6000, {
466f00add96SNiklas Söderlund 			  0x01c0bc40, 0x01c0bc40, 0x04c13052,
467f00add96SNiklas Söderlund 			  0x01e0c841, 0x01a0b43d, 0x04c13851,
468f00add96SNiklas Söderlund 			  0x0210cc44, 0x0180a83c, 0x04a13453,
469f00add96SNiklas Söderlund 			  0x0230d845, 0x0160a03a, 0x04913c52,
470f00add96SNiklas Söderlund 			  0x0260e047, 0x01409838, 0x04714052,
471f00add96SNiklas Söderlund 			  0x0280ec49, 0x01208c37, 0x04514c50,
472f00add96SNiklas Söderlund 			  0x02b0f44b, 0x01008435, 0x04414c50,
473f00add96SNiklas Söderlund 			  0x02d1004c, 0x00e07c33, 0x0431544f },
474f00add96SNiklas Söderlund 	},
475f00add96SNiklas Söderlund 	{ 0x7000, {
476f00add96SNiklas Söderlund 			  0x0230c83e, 0x0230c83e, 0x04711c4c,
477f00add96SNiklas Söderlund 			  0x0250d03f, 0x0210c43c, 0x0471204b,
478f00add96SNiklas Söderlund 			  0x0270d840, 0x0200b83c, 0x0451244b,
479f00add96SNiklas Söderlund 			  0x0290dc42, 0x01e0b43a, 0x0441244c,
480f00add96SNiklas Söderlund 			  0x02b0e443, 0x01c0b038, 0x0441284b,
481f00add96SNiklas Söderlund 			  0x02d0ec44, 0x01b0a438, 0x0421304a,
482f00add96SNiklas Söderlund 			  0x02f0f445, 0x0190a036, 0x04213449,
483f00add96SNiklas Söderlund 			  0x0310f847, 0x01709c34, 0x04213848 },
484f00add96SNiklas Söderlund 	},
485f00add96SNiklas Söderlund 	{ 0x8000, {
486f00add96SNiklas Söderlund 			  0x0280d03d, 0x0280d03d, 0x04310c48,
487f00add96SNiklas Söderlund 			  0x02a0d43e, 0x0270c83c, 0x04311047,
488f00add96SNiklas Söderlund 			  0x02b0dc3e, 0x0250c83a, 0x04311447,
489f00add96SNiklas Söderlund 			  0x02d0e040, 0x0240c03a, 0x04211446,
490f00add96SNiklas Söderlund 			  0x02e0e840, 0x0220bc39, 0x04111847,
491f00add96SNiklas Söderlund 			  0x0300e842, 0x0210b438, 0x04012445,
492f00add96SNiklas Söderlund 			  0x0310f043, 0x0200b037, 0x04012045,
493f00add96SNiklas Söderlund 			  0x0330f444, 0x01e0ac36, 0x03f12445 },
494f00add96SNiklas Söderlund 	},
495f00add96SNiklas Söderlund 	{ 0xefff, {
496f00add96SNiklas Söderlund 			  0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
497f00add96SNiklas Söderlund 			  0x0340e03a, 0x0330e039, 0x03c0f03e,
498f00add96SNiklas Söderlund 			  0x0350e03b, 0x0330dc39, 0x03c0ec3e,
499f00add96SNiklas Söderlund 			  0x0350e43a, 0x0320dc38, 0x03c0f43e,
500f00add96SNiklas Söderlund 			  0x0360e43b, 0x0320d839, 0x03b0f03e,
501f00add96SNiklas Söderlund 			  0x0360e83b, 0x0310d838, 0x03c0fc3b,
502f00add96SNiklas Söderlund 			  0x0370e83b, 0x0310d439, 0x03a0f83d,
503f00add96SNiklas Söderlund 			  0x0370e83c, 0x0300d438, 0x03b0fc3c },
504f00add96SNiklas Söderlund 	}
505f00add96SNiklas Söderlund };
506f00add96SNiklas Söderlund 
rvin_set_coeff(struct rvin_dev * vin,unsigned short xs)507f00add96SNiklas Söderlund static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
508f00add96SNiklas Söderlund {
509f00add96SNiklas Söderlund 	int i;
510f00add96SNiklas Söderlund 	const struct vin_coeff *p_prev_set = NULL;
511f00add96SNiklas Söderlund 	const struct vin_coeff *p_set = NULL;
512f00add96SNiklas Söderlund 
513f00add96SNiklas Söderlund 	/* Look for suitable coefficient values */
514f00add96SNiklas Söderlund 	for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
515f00add96SNiklas Söderlund 		p_prev_set = p_set;
516f00add96SNiklas Söderlund 		p_set = &vin_coeff_set[i];
517f00add96SNiklas Söderlund 
518bf78f23aSMauro Carvalho Chehab 		if (xs < p_set->xs_value)
519f00add96SNiklas Söderlund 			break;
520f00add96SNiklas Söderlund 	}
521f00add96SNiklas Söderlund 
522f00add96SNiklas Söderlund 	/* Use previous value if its XS value is closer */
523f00add96SNiklas Söderlund 	if (p_prev_set &&
524f00add96SNiklas Söderlund 	    xs - p_prev_set->xs_value < p_set->xs_value - xs)
525f00add96SNiklas Söderlund 		p_set = p_prev_set;
526f00add96SNiklas Söderlund 
527f00add96SNiklas Söderlund 	/* Set coefficient registers */
528f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[0], VNC1A_REG);
529f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[1], VNC1B_REG);
530f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[2], VNC1C_REG);
531f00add96SNiklas Söderlund 
532f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[3], VNC2A_REG);
533f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[4], VNC2B_REG);
534f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[5], VNC2C_REG);
535f00add96SNiklas Söderlund 
536f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[6], VNC3A_REG);
537f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[7], VNC3B_REG);
538f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[8], VNC3C_REG);
539f00add96SNiklas Söderlund 
540f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[9], VNC4A_REG);
541f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[10], VNC4B_REG);
542f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[11], VNC4C_REG);
543f00add96SNiklas Söderlund 
544f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[12], VNC5A_REG);
545f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[13], VNC5B_REG);
546f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[14], VNC5C_REG);
547f00add96SNiklas Söderlund 
548f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[15], VNC6A_REG);
549f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[16], VNC6B_REG);
550f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[17], VNC6C_REG);
551f00add96SNiklas Söderlund 
552f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[18], VNC7A_REG);
553f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[19], VNC7B_REG);
554f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[20], VNC7C_REG);
555f00add96SNiklas Söderlund 
5563ad69c61SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[21], VNC8A_REG);
557f00add96SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[22], VNC8B_REG);
55808369321SNiklas Söderlund 	rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
559f00add96SNiklas Söderlund }
560f00add96SNiklas Söderlund 
rvin_scaler_gen2(struct rvin_dev * vin)561f00add96SNiklas Söderlund void rvin_scaler_gen2(struct rvin_dev *vin)
56208369321SNiklas Söderlund {
5637e0cfdadSNiklas Söderlund 	u32 xs, ys;
56408369321SNiklas Söderlund 
56508369321SNiklas Söderlund 	/* Set scaling coefficient */
566f00add96SNiklas Söderlund 	ys = 0;
56708369321SNiklas Söderlund 	if (vin->crop.height != vin->compose.height)
56808369321SNiklas Söderlund 		ys = (4096 * vin->crop.height) / vin->compose.height;
569f00add96SNiklas Söderlund 	rvin_write(vin, ys, VNYS_REG);
570f00add96SNiklas Söderlund 
571f00add96SNiklas Söderlund 	xs = 0;
572f00add96SNiklas Söderlund 	if (vin->crop.width != vin->compose.width)
573f00add96SNiklas Söderlund 		xs = (4096 * vin->crop.width) / vin->compose.width;
574f00add96SNiklas Söderlund 
575f00add96SNiklas Söderlund 	/* Horizontal upscaling is up to double size */
576f00add96SNiklas Söderlund 	if (xs > 0 && xs < 2048)
577f00add96SNiklas Söderlund 		xs = 2048;
578f00add96SNiklas Söderlund 
579f00add96SNiklas Söderlund 	rvin_write(vin, xs, VNXS_REG);
580f00add96SNiklas Söderlund 
581f00add96SNiklas Söderlund 	/* Horizontal upscaling is done out by scaling down from double size */
582f00add96SNiklas Söderlund 	if (xs < 4096)
583f00add96SNiklas Söderlund 		xs *= 2;
584f00add96SNiklas Söderlund 
585f00add96SNiklas Söderlund 	rvin_set_coeff(vin, xs);
586f00add96SNiklas Söderlund 
587f00add96SNiklas Söderlund 	/* Set Start/End Pixel/Line Post-Clip */
588f00add96SNiklas Söderlund 	rvin_write(vin, 0, VNSPPOC_REG);
589f00add96SNiklas Söderlund 	rvin_write(vin, 0, VNSLPOC_REG);
590f00add96SNiklas Söderlund 	rvin_write(vin, vin->format.width - 1, VNEPPOC_REG);
591d23e12dcSNiklas Söderlund 
5927e0cfdadSNiklas Söderlund 	if (V4L2_FIELD_HAS_BOTH(vin->format.field))
593f00add96SNiklas Söderlund 		rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG);
594d23e12dcSNiklas Söderlund 	else
595f00add96SNiklas Söderlund 		rvin_write(vin, vin->format.height - 1, VNELPOC_REG);
596f00add96SNiklas Söderlund 
597f00add96SNiklas Söderlund 	vin_dbg(vin,
598f00add96SNiklas Söderlund 		"Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n",
599f00add96SNiklas Söderlund 		vin->crop.width, vin->crop.height, vin->crop.left,
600f00add96SNiklas Söderlund 		vin->crop.top, ys, xs, vin->format.width, vin->format.height,
601f00add96SNiklas Söderlund 		0, 0);
602f00add96SNiklas Söderlund }
603f00add96SNiklas Söderlund 
rvin_uds_scale_ratio(unsigned int in,unsigned int out)604928a6ea4SNiklas Söderlund static unsigned int rvin_uds_scale_ratio(unsigned int in, unsigned int out)
605928a6ea4SNiklas Söderlund {
606928a6ea4SNiklas Söderlund 	unsigned int ratio;
607928a6ea4SNiklas Söderlund 
608928a6ea4SNiklas Söderlund 	ratio = in * 4096 / out;
609928a6ea4SNiklas Söderlund 	return ratio >= 0x10000 ? 0xffff : ratio;
610928a6ea4SNiklas Söderlund }
611928a6ea4SNiklas Söderlund 
rvin_uds_filter_width(unsigned int ratio)612928a6ea4SNiklas Söderlund static unsigned int rvin_uds_filter_width(unsigned int ratio)
613928a6ea4SNiklas Söderlund {
614928a6ea4SNiklas Söderlund 	if (ratio >= 0x1000)
615928a6ea4SNiklas Söderlund 		return 64 * (ratio & 0xf000) / ratio;
616928a6ea4SNiklas Söderlund 
617928a6ea4SNiklas Söderlund 	return 64;
618928a6ea4SNiklas Söderlund }
619928a6ea4SNiklas Söderlund 
rvin_scaler_gen3(struct rvin_dev * vin)620928a6ea4SNiklas Söderlund void rvin_scaler_gen3(struct rvin_dev *vin)
621928a6ea4SNiklas Söderlund {
622928a6ea4SNiklas Söderlund 	unsigned int ratio_h, ratio_v;
623928a6ea4SNiklas Söderlund 	unsigned int bwidth_h, bwidth_v;
624928a6ea4SNiklas Söderlund 	u32 vnmc, clip_size;
625928a6ea4SNiklas Söderlund 
626928a6ea4SNiklas Söderlund 	vnmc = rvin_read(vin, VNMC_REG);
627928a6ea4SNiklas Söderlund 
628928a6ea4SNiklas Söderlund 	/* Disable scaler if not needed. */
629928a6ea4SNiklas Söderlund 	if (!rvin_scaler_needed(vin)) {
630928a6ea4SNiklas Söderlund 		rvin_write(vin, vnmc & ~VNMC_SCLE, VNMC_REG);
631928a6ea4SNiklas Söderlund 		return;
632928a6ea4SNiklas Söderlund 	}
633928a6ea4SNiklas Söderlund 
634928a6ea4SNiklas Söderlund 	ratio_h = rvin_uds_scale_ratio(vin->crop.width, vin->compose.width);
635928a6ea4SNiklas Söderlund 	bwidth_h = rvin_uds_filter_width(ratio_h);
636928a6ea4SNiklas Söderlund 
637928a6ea4SNiklas Söderlund 	ratio_v = rvin_uds_scale_ratio(vin->crop.height, vin->compose.height);
638928a6ea4SNiklas Söderlund 	bwidth_v = rvin_uds_filter_width(ratio_v);
639928a6ea4SNiklas Söderlund 
640928a6ea4SNiklas Söderlund 	clip_size = vin->compose.width << 16;
641928a6ea4SNiklas Söderlund 
642928a6ea4SNiklas Söderlund 	switch (vin->format.field) {
643928a6ea4SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_TB:
644928a6ea4SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_BT:
645928a6ea4SNiklas Söderlund 	case V4L2_FIELD_INTERLACED:
646928a6ea4SNiklas Söderlund 		clip_size |= vin->compose.height / 2;
647928a6ea4SNiklas Söderlund 		break;
648928a6ea4SNiklas Söderlund 	default:
649928a6ea4SNiklas Söderlund 		clip_size |= vin->compose.height;
650928a6ea4SNiklas Söderlund 		break;
651928a6ea4SNiklas Söderlund 	}
652928a6ea4SNiklas Söderlund 
653928a6ea4SNiklas Söderlund 	rvin_write(vin, vnmc | VNMC_SCLE, VNMC_REG);
654928a6ea4SNiklas Söderlund 	rvin_write(vin, VNUDS_CTRL_AMD, VNUDS_CTRL_REG);
655928a6ea4SNiklas Söderlund 	rvin_write(vin, (ratio_h << 16) | ratio_v, VNUDS_SCALE_REG);
656928a6ea4SNiklas Söderlund 	rvin_write(vin, (bwidth_h << 16) | bwidth_v, VNUDS_PASS_BWIDTH_REG);
657928a6ea4SNiklas Söderlund 	rvin_write(vin, clip_size, VNUDS_CLIP_SIZE_REG);
658928a6ea4SNiklas Söderlund 
659928a6ea4SNiklas Söderlund 	vin_dbg(vin, "Pre-Clip: %ux%u@%u:%u Post-Clip: %ux%u@%u:%u\n",
660928a6ea4SNiklas Söderlund 		vin->crop.width, vin->crop.height, vin->crop.left,
661928a6ea4SNiklas Söderlund 		vin->crop.top, vin->compose.width, vin->compose.height,
662928a6ea4SNiklas Söderlund 		vin->compose.left, vin->compose.top);
663928a6ea4SNiklas Söderlund }
664928a6ea4SNiklas Söderlund 
rvin_crop_scale_comp(struct rvin_dev * vin)6654394eb24SNiklas Söderlund void rvin_crop_scale_comp(struct rvin_dev *vin)
6664394eb24SNiklas Söderlund {
66784246ae3SNiklas Söderlund 	const struct rvin_video_format *fmt;
66884246ae3SNiklas Söderlund 	u32 stride;
66984246ae3SNiklas Söderlund 
6704394eb24SNiklas Söderlund 	/* Set Start/End Pixel/Line Pre-Clip */
6714394eb24SNiklas Söderlund 	rvin_write(vin, vin->crop.left, VNSPPRC_REG);
6724394eb24SNiklas Söderlund 	rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
6734394eb24SNiklas Söderlund 	rvin_write(vin, vin->crop.top, VNSLPRC_REG);
67408369321SNiklas Söderlund 	rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
67508369321SNiklas Söderlund 
6763ad69c61SNiklas Söderlund 	if (vin->scaler)
6773ad69c61SNiklas Söderlund 		vin->scaler(vin);
6784394eb24SNiklas Söderlund 
67984246ae3SNiklas Söderlund 	fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
68084246ae3SNiklas Söderlund 	stride = vin->format.bytesperline / fmt->bpp;
68184246ae3SNiklas Söderlund 	rvin_write(vin, stride, VNIS_REG);
6824394eb24SNiklas Söderlund }
6834394eb24SNiklas Söderlund 
684f00add96SNiklas Söderlund /* -----------------------------------------------------------------------------
6850f4b3378SNiklas Söderlund  * Hardware setup
6860f4b3378SNiklas Söderlund  */
6870f4b3378SNiklas Söderlund 
rvin_setup(struct rvin_dev * vin)6880f4b3378SNiklas Söderlund static int rvin_setup(struct rvin_dev *vin)
6890f4b3378SNiklas Söderlund {
690d73c3357SNiklas Söderlund 	u32 vnmc, dmr, dmr2, interrupts;
6910f4b3378SNiklas Söderlund 	bool progressive = false, output_is_yuv = false, input_is_yuv = false;
6920f4b3378SNiklas Söderlund 
6930f4b3378SNiklas Söderlund 	switch (vin->format.field) {
6940f4b3378SNiklas Söderlund 	case V4L2_FIELD_TOP:
6950f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_ODD;
6960f4b3378SNiklas Söderlund 		break;
6970f4b3378SNiklas Söderlund 	case V4L2_FIELD_BOTTOM:
6980f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_EVEN;
6990f4b3378SNiklas Söderlund 		break;
7000f4b3378SNiklas Söderlund 	case V4L2_FIELD_INTERLACED:
7010f4b3378SNiklas Söderlund 		/* Default to TB */
7020f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_FULL;
7030f4b3378SNiklas Söderlund 		break;
7045e7c6236SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_TB:
7050f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_FULL;
7060f4b3378SNiklas Söderlund 		break;
7070f4b3378SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_BT:
7080f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_FULL | VNMC_FOC;
7090f4b3378SNiklas Söderlund 		break;
7100f4b3378SNiklas Söderlund 	case V4L2_FIELD_NONE:
7110f4b3378SNiklas Söderlund 	case V4L2_FIELD_ALTERNATE:
7120f4b3378SNiklas Söderlund 		vnmc = VNMC_IM_ODD_EVEN;
7130f4b3378SNiklas Söderlund 		progressive = true;
71408369321SNiklas Söderlund 		break;
71508369321SNiklas Söderlund 	default:
716e10707d5SNiklas Söderlund 		vnmc = VNMC_IM_ODD;
71708369321SNiklas Söderlund 		break;
7180f4b3378SNiklas Söderlund 	}
7190f4b3378SNiklas Söderlund 
7200f4b3378SNiklas Söderlund 	/*
7210f4b3378SNiklas Söderlund 	 * Input interface
7220f4b3378SNiklas Söderlund 	 */
7230f4b3378SNiklas Söderlund 	switch (vin->mbus_code) {
7240f4b3378SNiklas Söderlund 	case MEDIA_BUS_FMT_YUYV8_1X16:
7250f4b3378SNiklas Söderlund 		if (vin->is_csi)
726c65c99b4SNiklas Söderlund 			/* YCbCr422 8-bit */
7270f4b3378SNiklas Söderlund 			vnmc |= VNMC_INF_YUV8_BT601;
7289caf253eSJacopo Mondi 		else
7299caf253eSJacopo Mondi 			/* BT.601/BT.1358 16bit YCbCr422 */
7309caf253eSJacopo Mondi 			vnmc |= VNMC_INF_YUV16;
7319caf253eSJacopo Mondi 		input_is_yuv = true;
7320f4b3378SNiklas Söderlund 		break;
7330f4b3378SNiklas Söderlund 	case MEDIA_BUS_FMT_UYVY8_1X16:
7340f4b3378SNiklas Söderlund 		if (vin->is_csi)
7350f4b3378SNiklas Söderlund 			/* YCbCr422 8-bit */
73601d72e9dSNiklas Söderlund 			vnmc |= VNMC_INF_YUV8_BT601;
7379caf253eSJacopo Mondi 		else
7389caf253eSJacopo Mondi 			/* BT.601/BT.1358 16bit YCbCr422 */
7399caf253eSJacopo Mondi 			vnmc |= VNMC_INF_YUV16;
7409caf253eSJacopo Mondi 		vnmc |= VNMC_YCAL;
7419caf253eSJacopo Mondi 		input_is_yuv = true;
7429caf253eSJacopo Mondi 		break;
7439caf253eSJacopo Mondi 	case MEDIA_BUS_FMT_UYVY8_2X8:
74401d72e9dSNiklas Söderlund 		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
74501d72e9dSNiklas Söderlund 		if (!vin->is_csi &&
7460f4b3378SNiklas Söderlund 		    vin->parallel.mbus_type == V4L2_MBUS_BT656)
7470f4b3378SNiklas Söderlund 			vnmc |= VNMC_INF_YUV8_BT656;
748158e2a53SJacopo Mondi 		else
749d7592b2eSNiklas Söderlund 			vnmc |= VNMC_INF_YUV8_BT601;
750158e2a53SJacopo Mondi 
751158e2a53SJacopo Mondi 		input_is_yuv = true;
752158e2a53SJacopo Mondi 		break;
753158e2a53SJacopo Mondi 	case MEDIA_BUS_FMT_RGB888_1X24:
7540f4b3378SNiklas Söderlund 		vnmc |= VNMC_INF_RGB888;
7550f4b3378SNiklas Söderlund 		break;
7560f4b3378SNiklas Söderlund 	case MEDIA_BUS_FMT_UYVY10_2X10:
7570f4b3378SNiklas Söderlund 		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
7580f4b3378SNiklas Söderlund 		if (!vin->is_csi &&
7590f4b3378SNiklas Söderlund 		    vin->parallel.mbus_type == V4L2_MBUS_BT656)
7600f4b3378SNiklas Söderlund 			vnmc |= VNMC_INF_YUV10_BT656;
761158e2a53SJacopo Mondi 		else
762d7592b2eSNiklas Söderlund 			vnmc |= VNMC_INF_YUV10_BT601;
763158e2a53SJacopo Mondi 
764158e2a53SJacopo Mondi 		input_is_yuv = true;
765158e2a53SJacopo Mondi 		break;
766158e2a53SJacopo Mondi 	case MEDIA_BUS_FMT_SBGGR8_1X8:
7670f4b3378SNiklas Söderlund 	case MEDIA_BUS_FMT_SGBRG8_1X8:
7680f4b3378SNiklas Söderlund 	case MEDIA_BUS_FMT_SGRBG8_1X8:
7698c3e0f67SNiklas Söderlund 	case MEDIA_BUS_FMT_SRGGB8_1X8:
7708c3e0f67SNiklas Söderlund 	case MEDIA_BUS_FMT_Y8_1X8:
7718c3e0f67SNiklas Söderlund 		vnmc |= VNMC_INF_RAW8;
772e87c1a81SLad Prabhakar 		if (vin->info->model == RCAR_GEN4)
773c93beb52SVladimir Barinov 			vnmc |= VNMC_EXINF_RAW8;
774e87c1a81SLad Prabhakar 		break;
77517b5496cSTomi Valkeinen 	case MEDIA_BUS_FMT_SBGGR10_1X10:
77617b5496cSTomi Valkeinen 	case MEDIA_BUS_FMT_SGBRG10_1X10:
777e87c1a81SLad Prabhakar 	case MEDIA_BUS_FMT_SGRBG10_1X10:
7781b7e7240SNiklas Söderlund 	case MEDIA_BUS_FMT_SRGGB10_1X10:
7791b7e7240SNiklas Söderlund 		vnmc |= VNMC_INF_RGB666;
7801b7e7240SNiklas Söderlund 		break;
7811b7e7240SNiklas Söderlund 	default:
7821b7e7240SNiklas Söderlund 		break;
7831b7e7240SNiklas Söderlund 	}
7840f4b3378SNiklas Söderlund 
7850f4b3378SNiklas Söderlund 	/* Enable VSYNC Field Toggle mode after one VSYNC input */
7860f4b3378SNiklas Söderlund 	if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4)
7870f4b3378SNiklas Söderlund 		dmr2 = VNDMR2_FTEV;
7888b72c18dSMauro Carvalho Chehab 	else
789d6a08667STomi Valkeinen 		dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
790d73c3357SNiklas Söderlund 
791d73c3357SNiklas Söderlund 	if (!vin->is_csi) {
7920f4b3378SNiklas Söderlund 		/* Hsync Signal Polarity Select */
7930f4b3378SNiklas Söderlund 		if (!(vin->parallel.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
794158e2a53SJacopo Mondi 			dmr2 |= VNDMR2_HPS;
7950f4b3378SNiklas Söderlund 
796d7592b2eSNiklas Söderlund 		/* Vsync Signal Polarity Select */
7970f4b3378SNiklas Söderlund 		if (!(vin->parallel.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
7980f4b3378SNiklas Söderlund 			dmr2 |= VNDMR2_VPS;
7990f4b3378SNiklas Söderlund 
800d7592b2eSNiklas Söderlund 		/* Data Enable Polarity Select */
8010f4b3378SNiklas Söderlund 		if (vin->parallel.bus.flags & V4L2_MBUS_DATA_ENABLE_LOW)
80253cf3100SJacopo Mondi 			dmr2 |= VNDMR2_CES;
80353cf3100SJacopo Mondi 
804d7592b2eSNiklas Söderlund 		switch (vin->mbus_code) {
80553cf3100SJacopo Mondi 		case MEDIA_BUS_FMT_UYVY8_2X8:
806e8834943SLad Prabhakar 			if (vin->parallel.bus.bus_width == 8 &&
807e8834943SLad Prabhakar 			    vin->parallel.bus.data_shift == 8)
808e8834943SLad Prabhakar 				dmr2 |= VNDMR2_YDS;
809d7592b2eSNiklas Söderlund 			break;
810d7592b2eSNiklas Söderlund 		default:
811e8834943SLad Prabhakar 			break;
812e8834943SLad Prabhakar 		}
813e8834943SLad Prabhakar 	}
814e8834943SLad Prabhakar 
815e8834943SLad Prabhakar 	/*
816158e2a53SJacopo Mondi 	 * Output format
8170f4b3378SNiklas Söderlund 	 */
8180f4b3378SNiklas Söderlund 	switch (vin->format.pixelformat) {
8190f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_NV12:
8200f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_NV16:
8210f4b3378SNiklas Söderlund 		rvin_write(vin,
8229b744a3eSNiklas Söderlund 			   ALIGN(vin->format.bytesperline * vin->format.height,
8230f4b3378SNiklas Söderlund 				 0x80), VNUVAOF_REG);
8240f4b3378SNiklas Söderlund 		dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ?
8255c9de1faSNiklas Söderlund 			VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP;
8265c9de1faSNiklas Söderlund 		output_is_yuv = true;
8279b744a3eSNiklas Söderlund 		break;
8289b744a3eSNiklas Söderlund 	case V4L2_PIX_FMT_YUYV:
8290f4b3378SNiklas Söderlund 		dmr = VNDMR_BPSM;
8300f4b3378SNiklas Söderlund 		output_is_yuv = true;
8310f4b3378SNiklas Söderlund 		break;
8320f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_UYVY:
8330f4b3378SNiklas Söderlund 		dmr = 0;
8340f4b3378SNiklas Söderlund 		output_is_yuv = true;
8350f4b3378SNiklas Söderlund 		break;
8360f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_XRGB555:
8370f4b3378SNiklas Söderlund 		dmr = VNDMR_DTMD_ARGB;
8380f4b3378SNiklas Söderlund 		break;
8390f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_RGB565:
84019ab1f64SNiklas Söderlund 		dmr = 0;
8410f4b3378SNiklas Söderlund 		break;
8420f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_XBGR32:
8430f4b3378SNiklas Söderlund 		/* Note: not supported on M1 */
8440f4b3378SNiklas Söderlund 		dmr = VNDMR_EXRGB;
8450f4b3378SNiklas Söderlund 		break;
8460f4b3378SNiklas Söderlund 	case V4L2_PIX_FMT_ARGB555:
8470f4b3378SNiklas Söderlund 		dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB;
8480f4b3378SNiklas Söderlund 		break;
8491d99e68cSNiklas Söderlund 	case V4L2_PIX_FMT_ABGR32:
8501d99e68cSNiklas Söderlund 		dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB;
8511d99e68cSNiklas Söderlund 		break;
8521d99e68cSNiklas Söderlund 	case V4L2_PIX_FMT_SBGGR8:
8531d99e68cSNiklas Söderlund 	case V4L2_PIX_FMT_SGBRG8:
8541d99e68cSNiklas Söderlund 	case V4L2_PIX_FMT_SGRBG8:
8558c3e0f67SNiklas Söderlund 	case V4L2_PIX_FMT_SRGGB8:
8568c3e0f67SNiklas Söderlund 		dmr = 0;
8578c3e0f67SNiklas Söderlund 		break;
858e87c1a81SLad Prabhakar 	case V4L2_PIX_FMT_GREY:
859e87c1a81SLad Prabhakar 		if (input_is_yuv) {
860e87c1a81SLad Prabhakar 			dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8;
861c93beb52SVladimir Barinov 			output_is_yuv = true;
862c93beb52SVladimir Barinov 		} else {
863c93beb52SVladimir Barinov 			dmr = 0;
864c93beb52SVladimir Barinov 		}
865c93beb52SVladimir Barinov 		break;
866c93beb52SVladimir Barinov 	case V4L2_PIX_FMT_SBGGR10:
867c93beb52SVladimir Barinov 	case V4L2_PIX_FMT_SGBRG10:
868c93beb52SVladimir Barinov 	case V4L2_PIX_FMT_SGRBG10:
8691b7e7240SNiklas Söderlund 	case V4L2_PIX_FMT_SRGGB10:
8701b7e7240SNiklas Söderlund 		dmr = VNDMR_RMODE_RAW10;
8711b7e7240SNiklas Söderlund 		break;
8721b7e7240SNiklas Söderlund 	default:
873*94bf847aSTomi Valkeinen 		vin_err(vin, "Invalid pixelformat (0x%x)\n",
8741b7e7240SNiklas Söderlund 			vin->format.pixelformat);
8750f4b3378SNiklas Söderlund 		return -EINVAL;
8760f4b3378SNiklas Söderlund 	}
8770f4b3378SNiklas Söderlund 
8780f4b3378SNiklas Söderlund 	/* Always update on field change */
8790f4b3378SNiklas Söderlund 	vnmc |= VNMC_VUP;
8800f4b3378SNiklas Söderlund 
8810f4b3378SNiklas Söderlund 	if (!vin->info->use_isp) {
8820f4b3378SNiklas Söderlund 		/* If input and output use the same colorspace, use bypass mode */
8830f4b3378SNiklas Söderlund 		if (input_is_yuv == output_is_yuv)
884406bb586SNiklas Söderlund 			vnmc |= VNMC_BPS;
8850f4b3378SNiklas Söderlund 
8860f4b3378SNiklas Söderlund 		if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) {
8870f4b3378SNiklas Söderlund 			/* Select between CSI-2 and parallel input */
8880f4b3378SNiklas Söderlund 			if (vin->is_csi)
889d6a08667STomi Valkeinen 				vnmc &= ~VNMC_DPINE;
890d24c029eSJacopo Mondi 			else
891158e2a53SJacopo Mondi 				vnmc |= VNMC_DPINE;
8924394eb24SNiklas Söderlund 		}
8934394eb24SNiklas Söderlund 	}
8944394eb24SNiklas Söderlund 
8954394eb24SNiklas Söderlund 	/* Progressive or interlaced mode */
896406bb586SNiklas Söderlund 	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
8974394eb24SNiklas Söderlund 	/* Enable VSYNC Rising Edge Detection. */
8980f4b3378SNiklas Söderlund 	interrupts |= VNIE_VRE;
8990f4b3378SNiklas Söderlund 
9000f4b3378SNiklas Söderlund 	/* Ack interrupts */
9010f4b3378SNiklas Söderlund 	rvin_write(vin, interrupts, VNINTS_REG);
9020f4b3378SNiklas Söderlund 	/* Enable interrupts */
9030f4b3378SNiklas Söderlund 	rvin_write(vin, interrupts, VNIE_REG);
9040f4b3378SNiklas Söderlund 	/* Start capturing */
9050f4b3378SNiklas Söderlund 	rvin_write(vin, dmr, VNDMR_REG);
9060f4b3378SNiklas Söderlund 	rvin_write(vin, dmr2, VNDMR2_REG);
9070f4b3378SNiklas Söderlund 
9080f4b3378SNiklas Söderlund 	/* Enable module */
9090f4b3378SNiklas Söderlund 	rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
9100f4b3378SNiklas Söderlund 
9110f4b3378SNiklas Söderlund 	return 0;
9120f4b3378SNiklas Söderlund }
9130f4b3378SNiklas Söderlund 
rvin_capture_active(struct rvin_dev * vin)9140f4b3378SNiklas Söderlund static bool rvin_capture_active(struct rvin_dev *vin)
9150f4b3378SNiklas Söderlund {
9160f4b3378SNiklas Söderlund 	return rvin_read(vin, VNMS_REG) & VNMS_CA;
9170f4b3378SNiklas Söderlund }
9180f4b3378SNiklas Söderlund 
rvin_get_active_field(struct rvin_dev * vin,u32 vnms)9190f4b3378SNiklas Söderlund static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
9200f4b3378SNiklas Söderlund {
9210f4b3378SNiklas Söderlund 	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
9220f4b3378SNiklas Söderlund 		/* If FS is set it is an Even field. */
9230f4b3378SNiklas Söderlund 		if (vnms & VNMS_FS)
9240f4b3378SNiklas Söderlund 			return V4L2_FIELD_BOTTOM;
9250f4b3378SNiklas Söderlund 		return V4L2_FIELD_TOP;
9260f4b3378SNiklas Söderlund 	}
9270f4b3378SNiklas Söderlund 
9280f4b3378SNiklas Söderlund 	return vin->format.field;
9290f4b3378SNiklas Söderlund }
9300f4b3378SNiklas Söderlund 
rvin_set_slot_addr(struct rvin_dev * vin,int slot,dma_addr_t addr)9310f4b3378SNiklas Söderlund static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
9320f4b3378SNiklas Söderlund {
9330f4b3378SNiklas Söderlund 	const struct rvin_video_format *fmt;
9340f4b3378SNiklas Söderlund 	int offsetx, offsety;
93508369321SNiklas Söderlund 	dma_addr_t offset;
93608369321SNiklas Söderlund 
93708369321SNiklas Söderlund 	fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
93808369321SNiklas Söderlund 
93908369321SNiklas Söderlund 	/*
94008369321SNiklas Söderlund 	 * There is no HW support for composition do the beast we can
94108369321SNiklas Söderlund 	 * by modifying the buffer offset
94208369321SNiklas Söderlund 	 */
94308369321SNiklas Söderlund 	offsetx = vin->compose.left * fmt->bpp;
94408369321SNiklas Söderlund 	offsety = vin->compose.top * vin->format.bytesperline;
94508369321SNiklas Söderlund 	offset = addr + offsetx + offsety;
94608369321SNiklas Söderlund 
9470f4b3378SNiklas Söderlund 	/*
9480f4b3378SNiklas Söderlund 	 * The address needs to be 128 bytes aligned. Driver should never accept
9490f4b3378SNiklas Söderlund 	 * settings that do not satisfy this in the first place...
9500f4b3378SNiklas Söderlund 	 */
9510f4b3378SNiklas Söderlund 	if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
9520f4b3378SNiklas Söderlund 		return;
95321a816e7SNiklas Söderlund 
9540f4b3378SNiklas Söderlund 	rvin_write(vin, offset, VNMB_REG(slot));
9550f4b3378SNiklas Söderlund }
9560f4b3378SNiklas Söderlund 
9570f4b3378SNiklas Söderlund /*
9580f4b3378SNiklas Söderlund  * Moves a buffer from the queue to the HW slot. If no buffer is
9590f4b3378SNiklas Söderlund  * available use the scratch buffer. The scratch buffer is never
9600f4b3378SNiklas Söderlund  * returned to userspace, its only function is to enable the capture
9610f4b3378SNiklas Söderlund  * loop to keep running.
9620f4b3378SNiklas Söderlund  */
rvin_fill_hw_slot(struct rvin_dev * vin,int slot)9630f4b3378SNiklas Söderlund static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
9640f4b3378SNiklas Söderlund {
9650f4b3378SNiklas Söderlund 	struct rvin_buffer *buf;
9660f4b3378SNiklas Söderlund 	struct vb2_v4l2_buffer *vbuf;
9670f4b3378SNiklas Söderlund 	dma_addr_t phys_addr;
9680f4b3378SNiklas Söderlund 
9690f4b3378SNiklas Söderlund 	/* A already populated slot shall never be overwritten. */
9700f4b3378SNiklas Söderlund 	if (WARN_ON(vin->buf_hw[slot].buffer))
9710f4b3378SNiklas Söderlund 		return;
9720f4b3378SNiklas Söderlund 
9730f4b3378SNiklas Söderlund 	if (list_empty(&vin->buf_list)) {
9740f4b3378SNiklas Söderlund 		vin->buf_hw[slot].buffer = NULL;
9750f4b3378SNiklas Söderlund 		phys_addr = vin->scratch_phys;
9760f4b3378SNiklas Söderlund 	} else {
9770f4b3378SNiklas Söderlund 		/* Keep track of buffer we give to HW */
9780f4b3378SNiklas Söderlund 		buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
9790f4b3378SNiklas Söderlund 		vbuf = &buf->vb;
9800f4b3378SNiklas Söderlund 		list_del_init(to_buf_list(vbuf));
9810f4b3378SNiklas Söderlund 		vin->buf_hw[slot].buffer = vbuf;
9820f4b3378SNiklas Söderlund 
9830f4b3378SNiklas Söderlund 		/* Setup DMA */
9840f4b3378SNiklas Söderlund 		phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
9850f4b3378SNiklas Söderlund 	}
986e72b7359SNiklas Söderlund 
9870f4b3378SNiklas Söderlund 	vin_dbg(vin, "Filling HW slot: %d buffer: %p\n",
9880f4b3378SNiklas Söderlund 		slot, vin->buf_hw[slot].buffer);
989c1eefe88SNiklas Söderlund 
990e72b7359SNiklas Söderlund 	vin->buf_hw[slot].phys = phys_addr;
9910f4b3378SNiklas Söderlund 	rvin_set_slot_addr(vin, slot, phys_addr);
9920f4b3378SNiklas Söderlund }
9930f4b3378SNiklas Söderlund 
rvin_capture_start(struct rvin_dev * vin)9940f4b3378SNiklas Söderlund static int rvin_capture_start(struct rvin_dev *vin)
9950f4b3378SNiklas Söderlund {
9960f4b3378SNiklas Söderlund 	int ret;
997e72b7359SNiklas Söderlund 
9980f4b3378SNiklas Söderlund 	for (unsigned int slot = 0; slot < HW_BUFFER_NUM; slot++) {
9990f4b3378SNiklas Söderlund 		vin->buf_hw[slot].buffer = NULL;
10000f4b3378SNiklas Söderlund 		rvin_fill_hw_slot(vin, slot);
10010f4b3378SNiklas Söderlund 	}
10020f4b3378SNiklas Söderlund 
1003f2f0cd89SNiklas Söderlund 	ret = rvin_setup(vin);
1004f2f0cd89SNiklas Söderlund 	if (ret)
10057e0cfdadSNiklas Söderlund 		return ret;
10067e0cfdadSNiklas Söderlund 
10070f4b3378SNiklas Söderlund 	rvin_crop_scale_comp(vin);
10080f4b3378SNiklas Söderlund 
10090f4b3378SNiklas Söderlund 	vin_dbg(vin, "Starting to capture\n");
10100f4b3378SNiklas Söderlund 
10110f4b3378SNiklas Söderlund 	/* Continuous Frame Capture Mode */
1012f2f0cd89SNiklas Söderlund 	rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
10130f4b3378SNiklas Söderlund 
1014f2f0cd89SNiklas Söderlund 	return 0;
10157e0cfdadSNiklas Söderlund }
10160f4b3378SNiklas Söderlund 
rvin_capture_stop(struct rvin_dev * vin)1017f2f0cd89SNiklas Söderlund static void rvin_capture_stop(struct rvin_dev *vin)
10180f4b3378SNiklas Söderlund {
10190f4b3378SNiklas Söderlund 	/* Set continuous & single transfer off */
10200f4b3378SNiklas Söderlund 	rvin_write(vin, 0, VNFC_REG);
10210f4b3378SNiklas Söderlund 
10220f4b3378SNiklas Söderlund 	/* Disable module */
10233ad69c61SNiklas Söderlund 	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
10243ad69c61SNiklas Söderlund }
10250f4b3378SNiklas Söderlund 
10260f4b3378SNiklas Söderlund /* -----------------------------------------------------------------------------
10270f4b3378SNiklas Söderlund  * DMA Functions
10280f4b3378SNiklas Söderlund  */
10290f4b3378SNiklas Söderlund 
10300f4b3378SNiklas Söderlund #define RVIN_TIMEOUT_MS 100
10310f4b3378SNiklas Söderlund #define RVIN_RETRIES 10
10320f4b3378SNiklas Söderlund 
rvin_irq(int irq,void * data)10330f4b3378SNiklas Söderlund static irqreturn_t rvin_irq(int irq, void *data)
10340f4b3378SNiklas Söderlund {
10350f4b3378SNiklas Söderlund 	struct rvin_dev *vin = data;
10360f4b3378SNiklas Söderlund 	u32 capture, status, vnms;
10370f4b3378SNiklas Söderlund 	int slot;
10380f4b3378SNiklas Söderlund 	unsigned int handled = 0;
10390f4b3378SNiklas Söderlund 	unsigned long flags;
10400f4b3378SNiklas Söderlund 
10410f4b3378SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
10420f4b3378SNiklas Söderlund 
1043f00add96SNiklas Söderlund 	status = rvin_read(vin, VNINTS_REG);
1044f00add96SNiklas Söderlund 	if (!status)
1045f00add96SNiklas Söderlund 		goto done;
1046f00add96SNiklas Söderlund 
1047f00add96SNiklas Söderlund 	rvin_write(vin, status, VNINTS_REG);
1048f00add96SNiklas Söderlund 	handled = 1;
1049f00add96SNiklas Söderlund 
1050f00add96SNiklas Söderlund 	/* Signal Start of Frame. */
1051f00add96SNiklas Söderlund 	if (status & VNINTS_VRS) {
1052b6f556cbSNiklas Söderlund 		struct v4l2_event event = {
1053f00add96SNiklas Söderlund 			.type = V4L2_EVENT_FRAME_SYNC,
1054dc9aec79SNiklas Söderlund 			.u.frame_sync.frame_sequence = vin->sequence,
1055f00add96SNiklas Söderlund 		};
1056f00add96SNiklas Söderlund 
1057f00add96SNiklas Söderlund 		v4l2_event_queue(&vin->vdev, &event);
1058f00add96SNiklas Söderlund 	}
1059f00add96SNiklas Söderlund 
1060f00add96SNiklas Söderlund 	/* Nothing to do if nothing was captured. */
1061f00add96SNiklas Söderlund 	capture = vin->format.field == V4L2_FIELD_NONE ||
1062f00add96SNiklas Söderlund 		vin->format.field == V4L2_FIELD_ALTERNATE ?
1063f00add96SNiklas Söderlund 		VNINTS_FIS : VNINTS_EFS;
1064f00add96SNiklas Söderlund 	if (!(status & capture))
1065f00add96SNiklas Söderlund 		goto done;
106630334d3dSNiklas Söderlund 
106730334d3dSNiklas Söderlund 	/* Nothing to do if not running. */
106830334d3dSNiklas Söderlund 	if (!vin->running) {
106930334d3dSNiklas Söderlund 		vin_dbg(vin, "IRQ while not running, ignoring\n");
1070c1eefe88SNiklas Söderlund 		goto done;
1071c1eefe88SNiklas Söderlund 	}
1072c1eefe88SNiklas Söderlund 
1073f00add96SNiklas Söderlund 	/* Prepare for capture and update state */
1074f00add96SNiklas Söderlund 	vnms = rvin_read(vin, VNMS_REG);
1075f00add96SNiklas Söderlund 	slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
1076f00add96SNiklas Söderlund 
1077b6f556cbSNiklas Söderlund 	/*
1078dc9aec79SNiklas Söderlund 	 * To hand buffers back in a known order to userspace start
1079f00add96SNiklas Söderlund 	 * to capture first from slot 0.
108023689ab1SNiklas Söderlund 	 */
108123689ab1SNiklas Söderlund 	if (!vin->sequence) {
108223689ab1SNiklas Söderlund 		if (slot != 0) {
108323689ab1SNiklas Söderlund 			vin_dbg(vin, "Starting sync slot: %d\n", slot);
108425482a98SNiklas Söderlund 			goto done;
108523689ab1SNiklas Söderlund 		}
108623689ab1SNiklas Söderlund 
108723689ab1SNiklas Söderlund 		vin_dbg(vin, "Capture start synced!\n");
108823689ab1SNiklas Söderlund 	}
108923689ab1SNiklas Söderlund 
109023689ab1SNiklas Söderlund 	/* Capture frame */
109123689ab1SNiklas Söderlund 	if (vin->buf_hw[slot].buffer) {
109223689ab1SNiklas Söderlund 		vin->buf_hw[slot].buffer->field =
1093f00add96SNiklas Söderlund 			rvin_get_active_field(vin, vnms);
1094e72b7359SNiklas Söderlund 		vin->buf_hw[slot].buffer->sequence = vin->sequence;
1095e72b7359SNiklas Söderlund 		vin->buf_hw[slot].buffer->vb2_buf.timestamp = ktime_get_ns();
1096e72b7359SNiklas Söderlund 		vb2_buffer_done(&vin->buf_hw[slot].buffer->vb2_buf,
1097e72b7359SNiklas Söderlund 				VB2_BUF_STATE_DONE);
1098e72b7359SNiklas Söderlund 		vin->buf_hw[slot].buffer = NULL;
1099e72b7359SNiklas Söderlund 	} else {
1100dc9aec79SNiklas Söderlund 		/* Scratch buffer was used, dropping frame. */
1101e72b7359SNiklas Söderlund 		vin_dbg(vin, "Dropping frame %u\n", vin->sequence);
1102dc9aec79SNiklas Söderlund 	}
1103dc9aec79SNiklas Söderlund 
1104dc9aec79SNiklas Söderlund 	vin->sequence++;
1105dc9aec79SNiklas Söderlund 
1106dc9aec79SNiklas Söderlund 	/* Prepare for next frame */
1107dc9aec79SNiklas Söderlund 	rvin_fill_hw_slot(vin, slot);
1108f00add96SNiklas Söderlund done:
1109f00add96SNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
1110dc9aec79SNiklas Söderlund 
1111f00add96SNiklas Söderlund 	return IRQ_RETVAL(handled);
1112f00add96SNiklas Söderlund }
1113f00add96SNiklas Söderlund 
return_unused_buffers(struct rvin_dev * vin,enum vb2_buffer_state state)1114f00add96SNiklas Söderlund static void return_unused_buffers(struct rvin_dev *vin,
1115f00add96SNiklas Söderlund 				  enum vb2_buffer_state state)
1116f00add96SNiklas Söderlund {
1117b83a18ccSNiklas Söderlund 	struct rvin_buffer *buf, *node;
1118f00add96SNiklas Söderlund 	unsigned long flags;
1119f00add96SNiklas Söderlund 
1120f00add96SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
112163a71dd8SNiklas Söderlund 
112263a71dd8SNiklas Söderlund 	list_for_each_entry_safe(buf, node, &vin->buf_list, list) {
112363a71dd8SNiklas Söderlund 		vb2_buffer_done(&buf->vb.vb2_buf, state);
11247e0cfdadSNiklas Söderlund 		list_del(&buf->list);
1125f00add96SNiklas Söderlund 	}
1126f00add96SNiklas Söderlund 
1127f00add96SNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
1128f00add96SNiklas Söderlund }
112963a71dd8SNiklas Söderlund 
rvin_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])113063a71dd8SNiklas Söderlund static int rvin_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1131f00add96SNiklas Söderlund 			    unsigned int *nplanes, unsigned int sizes[],
1132f00add96SNiklas Söderlund 			    struct device *alloc_devs[])
1133f00add96SNiklas Söderlund 
1134f00add96SNiklas Söderlund {
113536c0f8b3SHans Verkuil 	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1136f00add96SNiklas Söderlund 
1137f00add96SNiklas Söderlund 	/* Make sure the image size is large enough. */
1138f00add96SNiklas Söderlund 	if (*nplanes)
1139f00add96SNiklas Söderlund 		return sizes[0] < vin->format.sizeimage ? -EINVAL : 0;
1140f00add96SNiklas Söderlund 
1141f00add96SNiklas Söderlund 	*nplanes = 1;
1142f00add96SNiklas Söderlund 	sizes[0] = vin->format.sizeimage;
1143f00add96SNiklas Söderlund 
1144f00add96SNiklas Söderlund 	return 0;
1145f00add96SNiklas Söderlund };
1146f00add96SNiklas Söderlund 
rvin_buffer_prepare(struct vb2_buffer * vb)1147f00add96SNiklas Söderlund static int rvin_buffer_prepare(struct vb2_buffer *vb)
1148f00add96SNiklas Söderlund {
1149f00add96SNiklas Söderlund 	struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1150f00add96SNiklas Söderlund 	unsigned long size = vin->format.sizeimage;
1151f00add96SNiklas Söderlund 
1152f00add96SNiklas Söderlund 	if (vb2_plane_size(vb, 0) < size) {
1153f00add96SNiklas Söderlund 		vin_err(vin, "buffer too small (%lu < %lu)\n",
1154f00add96SNiklas Söderlund 			vb2_plane_size(vb, 0), size);
1155f00add96SNiklas Söderlund 		return -EINVAL;
1156f00add96SNiklas Söderlund 	}
1157f00add96SNiklas Söderlund 
1158f00add96SNiklas Söderlund 	vb2_set_plane_payload(vb, 0, size);
1159f00add96SNiklas Söderlund 
1160f00add96SNiklas Söderlund 	return 0;
1161f00add96SNiklas Söderlund }
1162f00add96SNiklas Söderlund 
rvin_buffer_queue(struct vb2_buffer * vb)1163f00add96SNiklas Söderlund static void rvin_buffer_queue(struct vb2_buffer *vb)
1164f00add96SNiklas Söderlund {
1165f00add96SNiklas Söderlund 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1166f00add96SNiklas Söderlund 	struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1167f00add96SNiklas Söderlund 	unsigned long flags;
1168f00add96SNiklas Söderlund 
1169f00add96SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
1170f00add96SNiklas Söderlund 
1171f00add96SNiklas Söderlund 	list_add_tail(to_buf_list(vbuf), &vin->buf_list);
1172f00add96SNiklas Söderlund 
1173f00add96SNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
1174f00add96SNiklas Söderlund }
1175f00add96SNiklas Söderlund 
rvin_mc_validate_format(struct rvin_dev * vin,struct v4l2_subdev * sd,struct media_pad * pad)1176f00add96SNiklas Söderlund static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
1177f00add96SNiklas Söderlund 				   struct media_pad *pad)
1178f00add96SNiklas Söderlund {
11797b7eb115SNiklas Söderlund 	struct v4l2_subdev_format fmt = {
11807b7eb115SNiklas Söderlund 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
11817b7eb115SNiklas Söderlund 	};
11827b7eb115SNiklas Söderlund 
11837b7eb115SNiklas Söderlund 	fmt.pad = pad->index;
11847b7eb115SNiklas Söderlund 	if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt))
11857b7eb115SNiklas Söderlund 		return -EPIPE;
11867b7eb115SNiklas Söderlund 
11877b7eb115SNiklas Söderlund 	switch (fmt.format.code) {
11887b7eb115SNiklas Söderlund 	case MEDIA_BUS_FMT_YUYV8_1X16:
11897b7eb115SNiklas Söderlund 	case MEDIA_BUS_FMT_UYVY8_1X16:
11907b7eb115SNiklas Söderlund 	case MEDIA_BUS_FMT_UYVY8_2X8:
11917b7eb115SNiklas Söderlund 	case MEDIA_BUS_FMT_UYVY10_2X10:
119201d72e9dSNiklas Söderlund 	case MEDIA_BUS_FMT_RGB888_1X24:
11937b7eb115SNiklas Söderlund 		break;
11947b7eb115SNiklas Söderlund 	case MEDIA_BUS_FMT_SBGGR8_1X8:
11957b7eb115SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR8)
1196fd22e8ebSLad Prabhakar 			return -EPIPE;
11978c3e0f67SNiklas Söderlund 		break;
11988c3e0f67SNiklas Söderlund 	case MEDIA_BUS_FMT_SGBRG8_1X8:
11998c3e0f67SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG8)
12008c3e0f67SNiklas Söderlund 			return -EPIPE;
12018c3e0f67SNiklas Söderlund 		break;
12028c3e0f67SNiklas Söderlund 	case MEDIA_BUS_FMT_SGRBG8_1X8:
12038c3e0f67SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG8)
12048c3e0f67SNiklas Söderlund 			return -EPIPE;
12058c3e0f67SNiklas Söderlund 		break;
12068c3e0f67SNiklas Söderlund 	case MEDIA_BUS_FMT_SRGGB8_1X8:
12078c3e0f67SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB8)
12088c3e0f67SNiklas Söderlund 			return -EPIPE;
1209fd22e8ebSLad Prabhakar 		break;
1210fd22e8ebSLad Prabhakar 	case MEDIA_BUS_FMT_Y8_1X8:
1211fd22e8ebSLad Prabhakar 		if (vin->format.pixelformat != V4L2_PIX_FMT_GREY)
12127b7eb115SNiklas Söderlund 			return -EPIPE;
1213c93beb52SVladimir Barinov 		break;
1214c93beb52SVladimir Barinov 	case MEDIA_BUS_FMT_SBGGR10_1X10:
1215c93beb52SVladimir Barinov 		if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR10)
1216c93beb52SVladimir Barinov 			return -EPIPE;
12171b7e7240SNiklas Söderlund 		break;
12181b7e7240SNiklas Söderlund 	case MEDIA_BUS_FMT_SGBRG10_1X10:
12191b7e7240SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG10)
12201b7e7240SNiklas Söderlund 			return -EPIPE;
12211b7e7240SNiklas Söderlund 		break;
12221b7e7240SNiklas Söderlund 	case MEDIA_BUS_FMT_SGRBG10_1X10:
12231b7e7240SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG10)
12241b7e7240SNiklas Söderlund 			return -EPIPE;
12251b7e7240SNiklas Söderlund 		break;
12261b7e7240SNiklas Söderlund 	case MEDIA_BUS_FMT_SRGGB10_1X10:
12271b7e7240SNiklas Söderlund 		if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB10)
12281b7e7240SNiklas Söderlund 			return -EPIPE;
12291b7e7240SNiklas Söderlund 		break;
12301b7e7240SNiklas Söderlund 	default:
12311b7e7240SNiklas Söderlund 		return -EPIPE;
12321b7e7240SNiklas Söderlund 	}
12337b7eb115SNiklas Söderlund 	vin->mbus_code = fmt.format.code;
12347b7eb115SNiklas Söderlund 
12357b7eb115SNiklas Söderlund 	switch (fmt.format.field) {
1236fd22e8ebSLad Prabhakar 	case V4L2_FIELD_TOP:
12377b7eb115SNiklas Söderlund 	case V4L2_FIELD_BOTTOM:
12387b7eb115SNiklas Söderlund 	case V4L2_FIELD_NONE:
12397b7eb115SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_TB:
12407b7eb115SNiklas Söderlund 	case V4L2_FIELD_INTERLACED_BT:
12417b7eb115SNiklas Söderlund 	case V4L2_FIELD_INTERLACED:
12427b7eb115SNiklas Söderlund 		/* Supported natively */
12437b7eb115SNiklas Söderlund 		break;
12447b7eb115SNiklas Söderlund 	case V4L2_FIELD_ALTERNATE:
12457b7eb115SNiklas Söderlund 		switch (vin->format.field) {
12467b7eb115SNiklas Söderlund 		case V4L2_FIELD_TOP:
12477b7eb115SNiklas Söderlund 		case V4L2_FIELD_BOTTOM:
12487b7eb115SNiklas Söderlund 		case V4L2_FIELD_NONE:
12497b7eb115SNiklas Söderlund 		case V4L2_FIELD_ALTERNATE:
12507b7eb115SNiklas Söderlund 			break;
12517b7eb115SNiklas Söderlund 		case V4L2_FIELD_INTERLACED_TB:
125208369321SNiklas Söderlund 		case V4L2_FIELD_INTERLACED_BT:
12537b7eb115SNiklas Söderlund 		case V4L2_FIELD_INTERLACED:
12547b7eb115SNiklas Söderlund 			/* Use VIN hardware to combine the two fields */
12557b7eb115SNiklas Söderlund 			fmt.format.height *= 2;
12567b7eb115SNiklas Söderlund 			break;
12577b7eb115SNiklas Söderlund 		default:
12587b7eb115SNiklas Söderlund 			return -EPIPE;
12597b7eb115SNiklas Söderlund 		}
12607b7eb115SNiklas Söderlund 		break;
12617b7eb115SNiklas Söderlund 	default:
12627b7eb115SNiklas Söderlund 		return -EPIPE;
12637b7eb115SNiklas Söderlund 	}
12647b7eb115SNiklas Söderlund 
12657b7eb115SNiklas Söderlund 	if (rvin_scaler_needed(vin)) {
12667b7eb115SNiklas Söderlund 		/* Gen3 can't scale NV12 */
12677b7eb115SNiklas Söderlund 		if ((vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) &&
12683ad69c61SNiklas Söderlund 		    vin->format.pixelformat == V4L2_PIX_FMT_NV12)
1269879c5a45SNiklas Söderlund 			return -EPIPE;
1270d6a08667STomi Valkeinen 
1271879c5a45SNiklas Söderlund 		if (!vin->scaler)
1272879c5a45SNiklas Söderlund 			return -EPIPE;
1273879c5a45SNiklas Söderlund 	} else {
12743ad69c61SNiklas Söderlund 		if (vin->format.pixelformat == V4L2_PIX_FMT_NV12) {
12753ad69c61SNiklas Söderlund 			if (ALIGN(fmt.format.width, 32) != vin->format.width ||
12763ad69c61SNiklas Söderlund 			    ALIGN(fmt.format.height, 32) != vin->format.height)
1277cb88d828SNiklas Söderlund 				return -EPIPE;
1278cb88d828SNiklas Söderlund 		} else {
1279cb88d828SNiklas Söderlund 			if (fmt.format.width != vin->format.width ||
1280cb88d828SNiklas Söderlund 			    fmt.format.height != vin->format.height)
1281cb88d828SNiklas Söderlund 				return -EPIPE;
12827b7eb115SNiklas Söderlund 		}
12833ad69c61SNiklas Söderlund 	}
12843ad69c61SNiklas Söderlund 
12853ad69c61SNiklas Söderlund 	if (fmt.format.code != vin->mbus_code)
1286cb88d828SNiklas Söderlund 		return -EPIPE;
12873ad69c61SNiklas Söderlund 
12883ad69c61SNiklas Söderlund 	return 0;
12897b7eb115SNiklas Söderlund }
12907b7eb115SNiklas Söderlund 
rvin_set_stream(struct rvin_dev * vin,int on)12917b7eb115SNiklas Söderlund static int rvin_set_stream(struct rvin_dev *vin, int on)
12927b7eb115SNiklas Söderlund {
12937b7eb115SNiklas Söderlund 	struct v4l2_subdev *sd;
12947b7eb115SNiklas Söderlund 	struct media_pad *pad;
12957b7eb115SNiklas Söderlund 	int ret;
12967b7eb115SNiklas Söderlund 
12977b7eb115SNiklas Söderlund 	pad = media_pad_remote_pad_first(&vin->pad);
12987b7eb115SNiklas Söderlund 	if (!pad)
12997b7eb115SNiklas Söderlund 		return -EPIPE;
13007b7eb115SNiklas Söderlund 
13017b7eb115SNiklas Söderlund 	sd = media_entity_to_v4l2_subdev(pad->entity);
1302d7592b2eSNiklas Söderlund 
13037b7eb115SNiklas Söderlund 	if (!on) {
13047b7eb115SNiklas Söderlund 		video_device_pipeline_stop(&vin->vdev);
13057b7eb115SNiklas Söderlund 		return v4l2_subdev_disable_streams(sd, pad->index, BIT_ULL(0));
13067b7eb115SNiklas Söderlund 	}
13077b7eb115SNiklas Söderlund 
1308b2e44430SLaurent Pinchart 	ret = rvin_mc_validate_format(vin, sd, pad);
13097b7eb115SNiklas Söderlund 	if (ret)
13107b7eb115SNiklas Söderlund 		return ret;
13117b7eb115SNiklas Söderlund 
13127b7eb115SNiklas Söderlund 	ret = video_device_pipeline_alloc_start(&vin->vdev);
13137b7eb115SNiklas Söderlund 	if (ret)
13147b7eb115SNiklas Söderlund 		return ret;
131512cecbf9STomi Valkeinen 
1316178c1be5STomi Valkeinen 	ret = v4l2_subdev_enable_streams(sd, pad->index, BIT_ULL(0));
13177b7eb115SNiklas Söderlund 	if (ret == -ENOIOCTLCMD)
13187b7eb115SNiklas Söderlund 		ret = 0;
13197b7eb115SNiklas Söderlund 	if (ret)
13207b7eb115SNiklas Söderlund 		video_device_pipeline_stop(&vin->vdev);
13217b7eb115SNiklas Söderlund 
13227b7eb115SNiklas Söderlund 	return ret;
13236eaff06aSTomi Valkeinen }
13247b7eb115SNiklas Söderlund 
rvin_start_streaming(struct rvin_dev * vin)13257b7eb115SNiklas Söderlund int rvin_start_streaming(struct rvin_dev *vin)
13267b7eb115SNiklas Söderlund {
1327178c1be5STomi Valkeinen 	unsigned long flags;
13287b7eb115SNiklas Söderlund 	int ret;
13297b7eb115SNiklas Söderlund 
13307b7eb115SNiklas Söderlund 	ret = rvin_set_stream(vin, 1);
133112cecbf9STomi Valkeinen 	if (ret)
13327b7eb115SNiklas Söderlund 		return ret;
13337b7eb115SNiklas Söderlund 
13347b7eb115SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
13357b7eb115SNiklas Söderlund 
133663a71dd8SNiklas Söderlund 	vin->sequence = 0;
1337f00add96SNiklas Söderlund 
1338f00add96SNiklas Söderlund 	ret = rvin_capture_start(vin);
1339f00add96SNiklas Söderlund 	if (ret)
1340f00add96SNiklas Söderlund 		rvin_set_stream(vin, 0);
13417b7eb115SNiklas Söderlund 
134263a71dd8SNiklas Söderlund 	vin->running = true;
134363a71dd8SNiklas Söderlund 
1344f00add96SNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
1345f00add96SNiklas Söderlund 
1346f00add96SNiklas Söderlund 	return ret;
1347f00add96SNiklas Söderlund }
1348f00add96SNiklas Söderlund 
rvin_start_streaming_vq(struct vb2_queue * vq,unsigned int count)1349f00add96SNiklas Söderlund static int rvin_start_streaming_vq(struct vb2_queue *vq, unsigned int count)
135063a71dd8SNiklas Söderlund {
13517b7eb115SNiklas Söderlund 	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1352f00add96SNiklas Söderlund 	int ret = -ENOMEM;
1353c1eefe88SNiklas Söderlund 
1354c1eefe88SNiklas Söderlund 	/* Allocate scratch buffer. */
1355f00add96SNiklas Söderlund 	vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
13566a8ffa8bSNiklas Söderlund 					  &vin->scratch_phys, GFP_KERNEL);
1357f00add96SNiklas Söderlund 	if (!vin->scratch)
1358f00add96SNiklas Söderlund 		goto err_scratch;
1359f00add96SNiklas Söderlund 
136063a71dd8SNiklas Söderlund 	ret = rvin_start_streaming(vin);
1361f00add96SNiklas Söderlund 	if (ret)
1362f00add96SNiklas Söderlund 		goto err_start;
136363a71dd8SNiklas Söderlund 
136463a71dd8SNiklas Söderlund 	return 0;
136563a71dd8SNiklas Söderlund err_start:
136663a71dd8SNiklas Söderlund 	dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
136763a71dd8SNiklas Söderlund 			  vin->scratch_phys);
136863a71dd8SNiklas Söderlund err_scratch:
136963a71dd8SNiklas Söderlund 	return_unused_buffers(vin, VB2_BUF_STATE_QUEUED);
137063a71dd8SNiklas Söderlund 
137163a71dd8SNiklas Söderlund 	return ret;
137263a71dd8SNiklas Söderlund }
137363a71dd8SNiklas Söderlund 
rvin_stop_streaming(struct rvin_dev * vin)137463a71dd8SNiklas Söderlund void rvin_stop_streaming(struct rvin_dev *vin)
137563a71dd8SNiklas Söderlund {
137663a71dd8SNiklas Söderlund 	unsigned long flags;
137763a71dd8SNiklas Söderlund 
137863a71dd8SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
137963a71dd8SNiklas Söderlund 
138063a71dd8SNiklas Söderlund 	if (!vin->running) {
138163a71dd8SNiklas Söderlund 		spin_unlock_irqrestore(&vin->qlock, flags);
138263a71dd8SNiklas Söderlund 		return;
138363a71dd8SNiklas Söderlund 	}
138463a71dd8SNiklas Söderlund 
138563a71dd8SNiklas Söderlund 	/* Wait for streaming to stop */
138663a71dd8SNiklas Söderlund 	for (unsigned int i = 0; i < RVIN_RETRIES; i++) {
1387f00add96SNiklas Söderlund 		rvin_capture_stop(vin);
1388f00add96SNiklas Söderlund 
1389f00add96SNiklas Söderlund 		/* Check if HW is stopped */
1390f00add96SNiklas Söderlund 		if (!rvin_capture_active(vin)) {
1391c1eefe88SNiklas Söderlund 			break;
1392c4f11535SNiklas Söderlund 		}
1393c4f11535SNiklas Söderlund 
1394c4f11535SNiklas Söderlund 		spin_unlock_irqrestore(&vin->qlock, flags);
1395c4f11535SNiklas Söderlund 		msleep(RVIN_TIMEOUT_MS);
1396f00add96SNiklas Söderlund 		spin_lock_irqsave(&vin->qlock, flags);
1397c1eefe88SNiklas Söderlund 	}
1398f00add96SNiklas Söderlund 
1399f00add96SNiklas Söderlund 	if (rvin_capture_active(vin))
1400f00add96SNiklas Söderlund 		vin_err(vin, "Hardware did not stop\n");
1401f00add96SNiklas Söderlund 
1402f00add96SNiklas Söderlund 	vin->running = false;
1403f00add96SNiklas Söderlund 
1404f00add96SNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
1405f00add96SNiklas Söderlund 
1406f00add96SNiklas Söderlund 	rvin_set_stream(vin, 0);
1407f00add96SNiklas Söderlund 
1408f00add96SNiklas Söderlund 	/* disable interrupts */
1409f00add96SNiklas Söderlund 	rvin_write(vin, 0, VNIE_REG);
1410c1eefe88SNiklas Söderlund 
1411c1eefe88SNiklas Söderlund 	/* Return unprocessed buffers from hardware. */
1412c1eefe88SNiklas Söderlund 	for (unsigned int i = 0; i < HW_BUFFER_NUM; i++) {
1413c1eefe88SNiklas Söderlund 		if (vin->buf_hw[i].buffer)
1414f00add96SNiklas Söderlund 			vb2_buffer_done(&vin->buf_hw[i].buffer->vb2_buf,
1415f00add96SNiklas Söderlund 					VB2_BUF_STATE_ERROR);
1416f00add96SNiklas Söderlund 	}
14177b7eb115SNiklas Söderlund 
1418f00add96SNiklas Söderlund }
1419f00add96SNiklas Söderlund 
rvin_stop_streaming_vq(struct vb2_queue * vq)1420f00add96SNiklas Söderlund static void rvin_stop_streaming_vq(struct vb2_queue *vq)
1421c1eefe88SNiklas Söderlund {
1422c1eefe88SNiklas Söderlund 	struct rvin_dev *vin = vb2_get_drv_priv(vq);
1423c1eefe88SNiklas Söderlund 
1424c1eefe88SNiklas Söderlund 	rvin_stop_streaming(vin);
1425c1eefe88SNiklas Söderlund 
1426c1eefe88SNiklas Söderlund 	/* Free scratch buffer. */
1427c1eefe88SNiklas Söderlund 	dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1428c1eefe88SNiklas Söderlund 			  vin->scratch_phys);
142963a71dd8SNiklas Söderlund 
143063a71dd8SNiklas Söderlund 	return_unused_buffers(vin, VB2_BUF_STATE_ERROR);
143163a71dd8SNiklas Söderlund }
143263a71dd8SNiklas Söderlund 
143363a71dd8SNiklas Söderlund static const struct vb2_ops rvin_qops = {
143463a71dd8SNiklas Söderlund 	.queue_setup		= rvin_queue_setup,
143563a71dd8SNiklas Söderlund 	.buf_prepare		= rvin_buffer_prepare,
14366a8ffa8bSNiklas Söderlund 	.buf_queue		= rvin_buffer_queue,
14376a8ffa8bSNiklas Söderlund 	.start_streaming	= rvin_start_streaming_vq,
14386a8ffa8bSNiklas Söderlund 	.stop_streaming		= rvin_stop_streaming_vq,
14396a8ffa8bSNiklas Söderlund };
144063a71dd8SNiklas Söderlund 
rvin_dma_unregister(struct rvin_dev * vin)144163a71dd8SNiklas Söderlund void rvin_dma_unregister(struct rvin_dev *vin)
1442f00add96SNiklas Söderlund {
1443f00add96SNiklas Söderlund 	mutex_destroy(&vin->lock);
1444b7b361f0SJulia Lawall 
1445f00add96SNiklas Söderlund 	v4l2_device_unregister(&vin->v4l2_dev);
1446f00add96SNiklas Söderlund }
1447f00add96SNiklas Söderlund 
rvin_dma_register(struct rvin_dev * vin,int irq)144863a71dd8SNiklas Söderlund int rvin_dma_register(struct rvin_dev *vin, int irq)
144963a71dd8SNiklas Söderlund {
1450f00add96SNiklas Söderlund 	struct vb2_queue *q = &vin->queue;
1451f00add96SNiklas Söderlund 	int i, ret;
1452d6ad012eSNiklas Söderlund 
1453f00add96SNiklas Söderlund 	/* Initialize the top-level structure */
1454f00add96SNiklas Söderlund 	ret = v4l2_device_register(vin->dev, &vin->v4l2_dev);
1455f00add96SNiklas Söderlund 	if (ret)
1456f00add96SNiklas Söderlund 		return ret;
1457f00add96SNiklas Söderlund 
1458f00add96SNiklas Söderlund 	mutex_init(&vin->lock);
1459d6ad012eSNiklas Söderlund 	INIT_LIST_HEAD(&vin->buf_list);
1460f00add96SNiklas Söderlund 
1461f00add96SNiklas Söderlund 	spin_lock_init(&vin->qlock);
1462f00add96SNiklas Söderlund 
1463f00add96SNiklas Söderlund 	for (i = 0; i < HW_BUFFER_NUM; i++)
1464f00add96SNiklas Söderlund 		vin->buf_hw[i].buffer = NULL;
1465f00add96SNiklas Söderlund 
1466f00add96SNiklas Söderlund 	/* buffer queue */
1467f00add96SNiklas Söderlund 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1468f00add96SNiklas Söderlund 	q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1469f00add96SNiklas Söderlund 	q->lock = &vin->lock;
1470f00add96SNiklas Söderlund 	q->drv_priv = vin;
1471f00add96SNiklas Söderlund 	q->buf_struct_size = sizeof(struct rvin_buffer);
1472f00add96SNiklas Söderlund 	q->ops = &rvin_qops;
1473f00add96SNiklas Söderlund 	q->mem_ops = &vb2_dma_contig_memops;
1474f00add96SNiklas Söderlund 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1475e72b7359SNiklas Söderlund 	q->min_queued_buffers = 4;
1476f00add96SNiklas Söderlund 	q->dev = vin->dev;
1477f00add96SNiklas Söderlund 
1478f00add96SNiklas Söderlund 	ret = vb2_queue_init(q);
1479f00add96SNiklas Söderlund 	if (ret < 0) {
1480f00add96SNiklas Söderlund 		vin_err(vin, "failed to initialize VB2 queue\n");
1481f00add96SNiklas Söderlund 		goto error;
1482f00add96SNiklas Söderlund 	}
1483f00add96SNiklas Söderlund 
1484f00add96SNiklas Söderlund 	/* irq */
1485f00add96SNiklas Söderlund 	ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED,
148680c2b40aSBenjamin Gaignard 			       KBUILD_MODNAME, vin);
148753ddcc68SHans Verkuil 	if (ret) {
1488f00add96SNiklas Söderlund 		vin_err(vin, "failed to request irq\n");
1489f00add96SNiklas Söderlund 		goto error;
1490f00add96SNiklas Söderlund 	}
1491f00add96SNiklas Söderlund 
1492f00add96SNiklas Söderlund 	return 0;
1493f00add96SNiklas Söderlund error:
1494f00add96SNiklas Söderlund 	rvin_dma_unregister(vin);
1495f00add96SNiklas Söderlund 
1496f00add96SNiklas Söderlund 	return ret;
1497f00add96SNiklas Söderlund }
1498f00add96SNiklas Söderlund 
1499f00add96SNiklas Söderlund /* -----------------------------------------------------------------------------
1500f00add96SNiklas Söderlund  * Gen3 CHSEL manipulation
1501f00add96SNiklas Söderlund  */
1502f00add96SNiklas Söderlund 
1503f00add96SNiklas Söderlund /*
1504f00add96SNiklas Söderlund  * There is no need to have locking around changing the routing
1505d6ad012eSNiklas Söderlund  * as it's only possible to do so when no VIN in the group is
1506f00add96SNiklas Söderlund  * streaming so nothing can race with the VNMC register.
1507f00add96SNiklas Söderlund  */
rvin_set_channel_routing(struct rvin_dev * vin,u8 chsel)1508f00add96SNiklas Söderlund int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
150990dedce9SNiklas Söderlund {
151090dedce9SNiklas Söderlund 	const struct rvin_group_route *route;
151190dedce9SNiklas Söderlund 	u32 ifmd = 0;
151290dedce9SNiklas Söderlund 	u32 vnmc;
151390dedce9SNiklas Söderlund 	int ret;
151490dedce9SNiklas Söderlund 
151590dedce9SNiklas Söderlund 	ret = pm_runtime_resume_and_get(vin->dev);
151690dedce9SNiklas Söderlund 	if (ret < 0)
151790dedce9SNiklas Söderlund 		return ret;
151890dedce9SNiklas Söderlund 
151990dedce9SNiklas Söderlund 	/* Make register writes take effect immediately. */
152090dedce9SNiklas Söderlund 	vnmc = rvin_read(vin, VNMC_REG);
1521fb25ca37SJacopo Mondi 	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
1522fb25ca37SJacopo Mondi 
1523fb25ca37SJacopo Mondi 	/*
152490dedce9SNiklas Söderlund 	 * Set data expansion mode to "pad with 0s" by inspecting the routes
152590dedce9SNiklas Söderlund 	 * table to find out which bit fields are available in the IFMD
1526334fe327SMauro Carvalho Chehab 	 * register. IFMD_DES1 controls data expansion mode for CSI20/21,
1527334fe327SMauro Carvalho Chehab 	 * IFMD_DES0 controls data expansion mode for CSI40/41.
152890dedce9SNiklas Söderlund 	 */
152990dedce9SNiklas Söderlund 	for (route = vin->info->routes; route->chsel; route++) {
153090dedce9SNiklas Söderlund 		if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21)
153190dedce9SNiklas Söderlund 			ifmd |= VNCSI_IFMD_DES1;
153290dedce9SNiklas Söderlund 		else
153390dedce9SNiklas Söderlund 			ifmd |= VNCSI_IFMD_DES0;
1534fb25ca37SJacopo Mondi 
1535fb25ca37SJacopo Mondi 		if (ifmd == (VNCSI_IFMD_DES0 | VNCSI_IFMD_DES1))
1536fb25ca37SJacopo Mondi 			break;
1537fb25ca37SJacopo Mondi 	}
1538fb25ca37SJacopo Mondi 
1539fb25ca37SJacopo Mondi 	if (ifmd) {
15403e52419eSNiklas Söderlund 		ifmd |= VNCSI_IFMD_CSI_CHSEL(chsel);
1541fb25ca37SJacopo Mondi 		rvin_write(vin, ifmd, VNCSI_IFMD_REG);
1542fb25ca37SJacopo Mondi 	}
1543fb25ca37SJacopo Mondi 
1544fb25ca37SJacopo Mondi 	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
154590dedce9SNiklas Söderlund 
1546fb25ca37SJacopo Mondi 	vin->chsel = chsel;
1547fb25ca37SJacopo Mondi 
1548fb25ca37SJacopo Mondi 	/* Restore VNMC. */
1549fb25ca37SJacopo Mondi 	rvin_write(vin, vnmc, VNMC_REG);
1550fb25ca37SJacopo Mondi 
1551fb25ca37SJacopo Mondi 	pm_runtime_put(vin->dev);
155290dedce9SNiklas Söderlund 
1553fb25ca37SJacopo Mondi 	return 0;
155490dedce9SNiklas Söderlund }
155590dedce9SNiklas Söderlund 
rvin_set_alpha(struct rvin_dev * vin,unsigned int alpha)155690dedce9SNiklas Söderlund void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha)
155743e36a22SNiklas Söderlund {
155843e36a22SNiklas Söderlund 	unsigned long flags;
155990dedce9SNiklas Söderlund 	u32 dmr;
156090dedce9SNiklas Söderlund 
156190dedce9SNiklas Söderlund 	spin_lock_irqsave(&vin->qlock, flags);
156290dedce9SNiklas Söderlund 
156390dedce9SNiklas Söderlund 	vin->alpha = alpha;
15648d19d5d0SNiklas Söderlund 
156590dedce9SNiklas Söderlund 	if (!vin->running)
15665720c733SNiklas Söderlund 		goto out;
15675720c733SNiklas Söderlund 
15685720c733SNiklas Söderlund 	switch (vin->format.pixelformat) {
15691d99e68cSNiklas Söderlund 	case V4L2_PIX_FMT_ARGB555:
15701d99e68cSNiklas Söderlund 		dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT;
15711d99e68cSNiklas Söderlund 		if (vin->alpha)
15721d99e68cSNiklas Söderlund 			dmr |= VNDMR_ABIT;
15731d99e68cSNiklas Söderlund 		break;
15745720c733SNiklas Söderlund 	case V4L2_PIX_FMT_ABGR32:
15751d99e68cSNiklas Söderlund 		dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK;
1576c1eefe88SNiklas Söderlund 		dmr |= VNDMR_A8BIT(vin->alpha);
15771d99e68cSNiklas Söderlund 		break;
15781d99e68cSNiklas Söderlund 	default:
15791d99e68cSNiklas Söderlund 		goto out;
15801d99e68cSNiklas Söderlund 	}
15811d99e68cSNiklas Söderlund 
15821d99e68cSNiklas Söderlund 	rvin_write(vin, dmr,  VNDMR_REG);
15831d99e68cSNiklas Söderlund out:
15841d99e68cSNiklas Söderlund 	spin_unlock_irqrestore(&vin->qlock, flags);
15851d99e68cSNiklas Söderlund }
15861d99e68cSNiklas Söderlund