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