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