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