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