1
2
3
4
5
6
7
8
9
10
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
23
24
25
26#define VNMC_REG 0x00
27#define VNMS_REG 0x04
28#define VNFC_REG 0x08
29#define VNSLPRC_REG 0x0C
30#define VNELPRC_REG 0x10
31#define VNSPPRC_REG 0x14
32#define VNEPPRC_REG 0x18
33#define VNIS_REG 0x2C
34#define VNMB_REG(m) (0x30 + ((m) << 2))
35#define VNIE_REG 0x40
36#define VNINTS_REG 0x44
37#define VNSI_REG 0x48
38#define VNMTC_REG 0x4C
39#define VNDMR_REG 0x58
40#define VNDMR2_REG 0x5C
41#define VNUVAOF_REG 0x60
42
43
44#define VNSLPOC_REG 0x1C
45#define VNELPOC_REG 0x20
46#define VNSPPOC_REG 0x24
47#define VNEPPOC_REG 0x28
48#define VNYS_REG 0x50
49#define VNXS_REG 0x54
50#define VNC1A_REG 0x80
51#define VNC1B_REG 0x84
52#define VNC1C_REG 0x88
53#define VNC2A_REG 0x90
54#define VNC2B_REG 0x94
55#define VNC2C_REG 0x98
56#define VNC3A_REG 0xA0
57#define VNC3B_REG 0xA4
58#define VNC3C_REG 0xA8
59#define VNC4A_REG 0xB0
60#define VNC4B_REG 0xB4
61#define VNC4C_REG 0xB8
62#define VNC5A_REG 0xC0
63#define VNC5B_REG 0xC4
64#define VNC5C_REG 0xC8
65#define VNC6A_REG 0xD0
66#define VNC6B_REG 0xD4
67#define VNC6C_REG 0xD8
68#define VNC7A_REG 0xE0
69#define VNC7B_REG 0xE4
70#define VNC7C_REG 0xE8
71#define VNC8A_REG 0xF0
72#define VNC8B_REG 0xF4
73#define VNC8C_REG 0xF8
74
75
76#define VNCSI_IFMD_REG 0x20
77
78
79
80#define VNMC_INF_MASK (7 << 16)
81#define VNMC_DPINE (1 << 27)
82#define VNMC_SCLE (1 << 26)
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
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
109#define VNFC_C_FRAME (1 << 1)
110#define VNFC_S_FRAME (1 << 0)
111
112
113#define VNIE_FIE (1 << 4)
114#define VNIE_EFE (1 << 1)
115
116
117#define VNINTS_FIS (1 << 4)
118
119
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
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
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
143struct 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
152static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
153{
154 iowrite32(value, vin->base + offset);
155}
156
157static u32 rvin_read(struct rvin_dev *vin, u32 offset)
158{
159 return ioread32(vin->base + offset);
160}
161
162
163
164
165
166struct vin_coeff {
167 unsigned short xs_value;
168 u32 coeff_set[24];
169};
170
171static 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
484static 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
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
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
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
538static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
539{
540 unsigned int crop_height;
541 u32 xs, ys;
542
543
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
558 if (xs > 0 && xs < 2048)
559 xs = 2048;
560
561 rvin_write(vin, xs, VNXS_REG);
562
563
564 if (xs < 4096)
565 xs *= 2;
566
567 rvin_set_coeff(vin, xs);
568
569
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
586void rvin_crop_scale_comp(struct rvin_dev *vin)
587{
588 const struct rvin_video_format *fmt;
589 u32 stride;
590
591
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
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
605
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
624
625
626static 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
640 vnmc = VNMC_IM_FULL;
641
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
667
668 switch (vin->mbus_code) {
669 case MEDIA_BUS_FMT_YUYV8_1X16:
670
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
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
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
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
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
743 if (!(vin->parallel.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
744 dmr2 |= VNDMR2_HPS;
745
746
747 if (!(vin->parallel.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
748 dmr2 |= VNDMR2_VPS;
749
750
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
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
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
823 vnmc |= VNMC_VUP;
824
825 if (!vin->info->use_isp) {
826
827 if (input_is_yuv == output_is_yuv)
828 vnmc |= VNMC_BPS;
829
830 if (vin->info->model == RCAR_GEN3) {
831
832 if (vin->is_csi)
833 vnmc &= ~VNMC_DPINE;
834 else
835 vnmc |= VNMC_DPINE;
836 }
837 }
838
839
840 interrupts = progressive ? VNIE_FIE : VNIE_EFE;
841
842
843 rvin_write(vin, interrupts, VNINTS_REG);
844
845 rvin_write(vin, interrupts, VNIE_REG);
846
847 rvin_write(vin, dmr, VNDMR_REG);
848 rvin_write(vin, dmr2, VNDMR2_REG);
849
850
851 rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
852
853 return 0;
854}
855
856static void rvin_disable_interrupts(struct rvin_dev *vin)
857{
858 rvin_write(vin, 0, VNIE_REG);
859}
860
861static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
862{
863 return rvin_read(vin, VNINTS_REG);
864}
865
866static void rvin_ack_interrupt(struct rvin_dev *vin)
867{
868 rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
869}
870
871static bool rvin_capture_active(struct rvin_dev *vin)
872{
873 return rvin_read(vin, VNMS_REG) & VNMS_CA;
874}
875
876static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
877{
878 if (vin->format.field == V4L2_FIELD_ALTERNATE) {
879
880 if (vnms & VNMS_FS)
881 return V4L2_FIELD_BOTTOM;
882 return V4L2_FIELD_TOP;
883 }
884
885 return vin->format.field;
886}
887
888static 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
898
899
900 offsetx = vin->compose.left * fmt->bpp;
901 offsety = vin->compose.top * vin->format.bytesperline;
902 offset = addr + offsetx + offsety;
903
904
905
906
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
916
917
918
919
920static 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
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
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
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
975static 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
996 rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
997
998 vin->state = STARTING;
999
1000 return 0;
1001}
1002
1003static void rvin_capture_stop(struct rvin_dev *vin)
1004{
1005
1006 rvin_write(vin, 0, VNFC_REG);
1007
1008
1009 rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
1010}
1011
1012
1013
1014
1015
1016#define RVIN_TIMEOUT_MS 100
1017#define RVIN_RETRIES 10
1018
1019static 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
1037 if (!(int_status & VNINTS_FIS))
1038 goto done;
1039
1040
1041 if (vin->state == STOPPED) {
1042 vin_dbg(vin, "IRQ while state stopped\n");
1043 goto done;
1044 }
1045
1046
1047 vnms = rvin_read(vin, VNMS_REG);
1048 slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
1049
1050
1051
1052
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
1065 if (vin->buf_hw[slot].buffer) {
1066
1067
1068
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
1085 vin_dbg(vin, "Dropping frame %u\n", vin->sequence);
1086 }
1087
1088 vin->sequence++;
1089
1090
1091 rvin_fill_hw_slot(vin, slot);
1092done:
1093 spin_unlock_irqrestore(&vin->qlock, flags);
1094
1095 return IRQ_RETVAL(handled);
1096}
1097
1098static 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
1114static 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
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
1131static 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
1147static 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
1160static 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
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
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
1245static int rvin_set_stream(struct rvin_dev *vin, int on)
1246{
1247 struct media_pipeline *pipe;
1248 struct media_device *mdev;
1249 struct v4l2_subdev *sd;
1250 struct media_pad *pad;
1251 int ret;
1252
1253
1254 if (!vin->info->use_mc) {
1255 ret = v4l2_subdev_call(vin->parallel.subdev, video, s_stream,
1256 on);
1257
1258 return ret == -ENOIOCTLCMD ? 0 : ret;
1259 }
1260
1261 pad = media_entity_remote_pad(&vin->pad);
1262 if (!pad)
1263 return -EPIPE;
1264
1265 sd = media_entity_to_v4l2_subdev(pad->entity);
1266
1267 if (!on) {
1268 media_pipeline_stop(&vin->vdev.entity);
1269 return v4l2_subdev_call(sd, video, s_stream, 0);
1270 }
1271
1272 ret = rvin_mc_validate_format(vin, sd, pad);
1273 if (ret)
1274 return ret;
1275
1276
1277
1278
1279
1280
1281
1282 mdev = vin->vdev.entity.graph_obj.mdev;
1283 mutex_lock(&mdev->graph_mutex);
1284 pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe;
1285 ret = __media_pipeline_start(&vin->vdev.entity, pipe);
1286 mutex_unlock(&mdev->graph_mutex);
1287 if (ret)
1288 return ret;
1289
1290 ret = v4l2_subdev_call(sd, video, s_stream, 1);
1291 if (ret == -ENOIOCTLCMD)
1292 ret = 0;
1293 if (ret)
1294 media_pipeline_stop(&vin->vdev.entity);
1295
1296 return ret;
1297}
1298
1299int rvin_start_streaming(struct rvin_dev *vin)
1300{
1301 unsigned long flags;
1302 int ret;
1303
1304 ret = rvin_set_stream(vin, 1);
1305 if (ret)
1306 return ret;
1307
1308 spin_lock_irqsave(&vin->qlock, flags);
1309
1310 vin->sequence = 0;
1311
1312 ret = rvin_capture_start(vin);
1313 if (ret)
1314 rvin_set_stream(vin, 0);
1315
1316 spin_unlock_irqrestore(&vin->qlock, flags);
1317
1318 return ret;
1319}
1320
1321static int rvin_start_streaming_vq(struct vb2_queue *vq, unsigned int count)
1322{
1323 struct rvin_dev *vin = vb2_get_drv_priv(vq);
1324 int ret = -ENOMEM;
1325
1326
1327 vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
1328 &vin->scratch_phys, GFP_KERNEL);
1329 if (!vin->scratch)
1330 goto err_scratch;
1331
1332 ret = rvin_start_streaming(vin);
1333 if (ret)
1334 goto err_start;
1335
1336 return 0;
1337err_start:
1338 dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1339 vin->scratch_phys);
1340err_scratch:
1341 return_unused_buffers(vin, VB2_BUF_STATE_QUEUED);
1342
1343 return ret;
1344}
1345
1346void rvin_stop_streaming(struct rvin_dev *vin)
1347{
1348 unsigned int i, retries;
1349 unsigned long flags;
1350 bool buffersFreed;
1351
1352 spin_lock_irqsave(&vin->qlock, flags);
1353
1354 if (vin->state == STOPPED) {
1355 spin_unlock_irqrestore(&vin->qlock, flags);
1356 return;
1357 }
1358
1359 vin->state = STOPPING;
1360
1361
1362 retries = 0;
1363 while (retries++ < RVIN_RETRIES) {
1364 buffersFreed = true;
1365 for (i = 0; i < HW_BUFFER_NUM; i++)
1366 if (vin->buf_hw[i].buffer)
1367 buffersFreed = false;
1368
1369 if (buffersFreed)
1370 break;
1371
1372 spin_unlock_irqrestore(&vin->qlock, flags);
1373 msleep(RVIN_TIMEOUT_MS);
1374 spin_lock_irqsave(&vin->qlock, flags);
1375 }
1376
1377
1378 retries = 0;
1379 while (retries++ < RVIN_RETRIES) {
1380
1381 rvin_capture_stop(vin);
1382
1383
1384 if (!rvin_capture_active(vin)) {
1385 vin->state = STOPPED;
1386 break;
1387 }
1388
1389 spin_unlock_irqrestore(&vin->qlock, flags);
1390 msleep(RVIN_TIMEOUT_MS);
1391 spin_lock_irqsave(&vin->qlock, flags);
1392 }
1393
1394 if (!buffersFreed || vin->state != STOPPED) {
1395
1396
1397
1398
1399
1400 vin_err(vin, "Failed stop HW, something is seriously broken\n");
1401 vin->state = STOPPED;
1402 }
1403
1404 spin_unlock_irqrestore(&vin->qlock, flags);
1405
1406
1407 if (!buffersFreed) {
1408 return_unused_buffers(vin, VB2_BUF_STATE_ERROR);
1409 for (i = 0; i < HW_BUFFER_NUM; i++) {
1410 if (vin->buf_hw[i].buffer)
1411 vb2_buffer_done(&vin->buf_hw[i].buffer->vb2_buf,
1412 VB2_BUF_STATE_ERROR);
1413 }
1414 }
1415
1416 rvin_set_stream(vin, 0);
1417
1418
1419 rvin_disable_interrupts(vin);
1420}
1421
1422static void rvin_stop_streaming_vq(struct vb2_queue *vq)
1423{
1424 struct rvin_dev *vin = vb2_get_drv_priv(vq);
1425
1426 rvin_stop_streaming(vin);
1427
1428
1429 dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1430 vin->scratch_phys);
1431
1432 return_unused_buffers(vin, VB2_BUF_STATE_ERROR);
1433}
1434
1435static const struct vb2_ops rvin_qops = {
1436 .queue_setup = rvin_queue_setup,
1437 .buf_prepare = rvin_buffer_prepare,
1438 .buf_queue = rvin_buffer_queue,
1439 .start_streaming = rvin_start_streaming_vq,
1440 .stop_streaming = rvin_stop_streaming_vq,
1441 .wait_prepare = vb2_ops_wait_prepare,
1442 .wait_finish = vb2_ops_wait_finish,
1443};
1444
1445void rvin_dma_unregister(struct rvin_dev *vin)
1446{
1447 mutex_destroy(&vin->lock);
1448
1449 v4l2_device_unregister(&vin->v4l2_dev);
1450}
1451
1452int rvin_dma_register(struct rvin_dev *vin, int irq)
1453{
1454 struct vb2_queue *q = &vin->queue;
1455 int i, ret;
1456
1457
1458 ret = v4l2_device_register(vin->dev, &vin->v4l2_dev);
1459 if (ret)
1460 return ret;
1461
1462 mutex_init(&vin->lock);
1463 INIT_LIST_HEAD(&vin->buf_list);
1464
1465 spin_lock_init(&vin->qlock);
1466
1467 vin->state = STOPPED;
1468
1469 for (i = 0; i < HW_BUFFER_NUM; i++)
1470 vin->buf_hw[i].buffer = NULL;
1471
1472
1473 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1474 q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1475 q->lock = &vin->lock;
1476 q->drv_priv = vin;
1477 q->buf_struct_size = sizeof(struct rvin_buffer);
1478 q->ops = &rvin_qops;
1479 q->mem_ops = &vb2_dma_contig_memops;
1480 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1481 q->min_buffers_needed = 4;
1482 q->dev = vin->dev;
1483
1484 ret = vb2_queue_init(q);
1485 if (ret < 0) {
1486 vin_err(vin, "failed to initialize VB2 queue\n");
1487 goto error;
1488 }
1489
1490
1491 ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED,
1492 KBUILD_MODNAME, vin);
1493 if (ret) {
1494 vin_err(vin, "failed to request irq\n");
1495 goto error;
1496 }
1497
1498 return 0;
1499error:
1500 rvin_dma_unregister(vin);
1501
1502 return ret;
1503}
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
1515{
1516 const struct rvin_group_route *route;
1517 u32 ifmd = 0;
1518 u32 vnmc;
1519 int ret;
1520
1521 ret = pm_runtime_resume_and_get(vin->dev);
1522 if (ret < 0)
1523 return ret;
1524
1525
1526 vnmc = rvin_read(vin, VNMC_REG);
1527 rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
1528
1529
1530
1531
1532
1533
1534
1535 for (route = vin->info->routes; route->chsel; route++) {
1536 if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21)
1537 ifmd |= VNCSI_IFMD_DES1;
1538 else
1539 ifmd |= VNCSI_IFMD_DES0;
1540
1541 if (ifmd == (VNCSI_IFMD_DES0 | VNCSI_IFMD_DES1))
1542 break;
1543 }
1544
1545 if (ifmd) {
1546 ifmd |= VNCSI_IFMD_CSI_CHSEL(chsel);
1547 rvin_write(vin, ifmd, VNCSI_IFMD_REG);
1548 }
1549
1550 vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
1551
1552 vin->chsel = chsel;
1553
1554
1555 rvin_write(vin, vnmc, VNMC_REG);
1556
1557 pm_runtime_put(vin->dev);
1558
1559 return 0;
1560}
1561
1562void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha)
1563{
1564 unsigned long flags;
1565 u32 dmr;
1566
1567 spin_lock_irqsave(&vin->qlock, flags);
1568
1569 vin->alpha = alpha;
1570
1571 if (vin->state == STOPPED)
1572 goto out;
1573
1574 switch (vin->format.pixelformat) {
1575 case V4L2_PIX_FMT_ARGB555:
1576 dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT;
1577 if (vin->alpha)
1578 dmr |= VNDMR_ABIT;
1579 break;
1580 case V4L2_PIX_FMT_ABGR32:
1581 dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK;
1582 dmr |= VNDMR_A8BIT(vin->alpha);
1583 break;
1584 default:
1585 goto out;
1586 }
1587
1588 rvin_write(vin, dmr, VNDMR_REG);
1589out:
1590 spin_unlock_irqrestore(&vin->qlock, flags);
1591}
1592