GNU Linux-libre 4.9.331-gnu1
[releases.git] / drivers / media / platform / rcar-vin / rcar-dma.c
1 /*
2  * Driver for Renesas R-Car VIN
3  *
4  * Copyright (C) 2016 Renesas Electronics Corp.
5  * Copyright (C) 2011-2013 Renesas Solutions Corp.
6  * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
7  * Copyright (C) 2008 Magnus Damm
8  *
9  * Based on the soc-camera rcar_vin driver
10  *
11  * This program is free software; you can redistribute  it and/or modify it
12  * under  the terms of  the GNU General  Public License as published by the
13  * Free Software Foundation;  either version 2 of the  License, or (at your
14  * option) any later version.
15  */
16
17 #include <linux/delay.h>
18 #include <linux/interrupt.h>
19
20 #include <media/videobuf2-dma-contig.h>
21
22 #include "rcar-vin.h"
23
24 /* -----------------------------------------------------------------------------
25  * HW Functions
26  */
27
28 /* Register offsets for R-Car VIN */
29 #define VNMC_REG        0x00    /* Video n Main Control Register */
30 #define VNMS_REG        0x04    /* Video n Module Status Register */
31 #define VNFC_REG        0x08    /* Video n Frame Capture Register */
32 #define VNSLPRC_REG     0x0C    /* Video n Start Line Pre-Clip Register */
33 #define VNELPRC_REG     0x10    /* Video n End Line Pre-Clip Register */
34 #define VNSPPRC_REG     0x14    /* Video n Start Pixel Pre-Clip Register */
35 #define VNEPPRC_REG     0x18    /* Video n End Pixel Pre-Clip Register */
36 #define VNSLPOC_REG     0x1C    /* Video n Start Line Post-Clip Register */
37 #define VNELPOC_REG     0x20    /* Video n End Line Post-Clip Register */
38 #define VNSPPOC_REG     0x24    /* Video n Start Pixel Post-Clip Register */
39 #define VNEPPOC_REG     0x28    /* Video n End Pixel Post-Clip Register */
40 #define VNIS_REG        0x2C    /* Video n Image Stride Register */
41 #define VNMB_REG(m)     (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
42 #define VNIE_REG        0x40    /* Video n Interrupt Enable Register */
43 #define VNINTS_REG      0x44    /* Video n Interrupt Status Register */
44 #define VNSI_REG        0x48    /* Video n Scanline Interrupt Register */
45 #define VNMTC_REG       0x4C    /* Video n Memory Transfer Control Register */
46 #define VNYS_REG        0x50    /* Video n Y Scale Register */
47 #define VNXS_REG        0x54    /* Video n X Scale Register */
48 #define VNDMR_REG       0x58    /* Video n Data Mode Register */
49 #define VNDMR2_REG      0x5C    /* Video n Data Mode Register 2 */
50 #define VNUVAOF_REG     0x60    /* Video n UV Address Offset Register */
51 #define VNC1A_REG       0x80    /* Video n Coefficient Set C1A Register */
52 #define VNC1B_REG       0x84    /* Video n Coefficient Set C1B Register */
53 #define VNC1C_REG       0x88    /* Video n Coefficient Set C1C Register */
54 #define VNC2A_REG       0x90    /* Video n Coefficient Set C2A Register */
55 #define VNC2B_REG       0x94    /* Video n Coefficient Set C2B Register */
56 #define VNC2C_REG       0x98    /* Video n Coefficient Set C2C Register */
57 #define VNC3A_REG       0xA0    /* Video n Coefficient Set C3A Register */
58 #define VNC3B_REG       0xA4    /* Video n Coefficient Set C3B Register */
59 #define VNC3C_REG       0xA8    /* Video n Coefficient Set C3C Register */
60 #define VNC4A_REG       0xB0    /* Video n Coefficient Set C4A Register */
61 #define VNC4B_REG       0xB4    /* Video n Coefficient Set C4B Register */
62 #define VNC4C_REG       0xB8    /* Video n Coefficient Set C4C Register */
63 #define VNC5A_REG       0xC0    /* Video n Coefficient Set C5A Register */
64 #define VNC5B_REG       0xC4    /* Video n Coefficient Set C5B Register */
65 #define VNC5C_REG       0xC8    /* Video n Coefficient Set C5C Register */
66 #define VNC6A_REG       0xD0    /* Video n Coefficient Set C6A Register */
67 #define VNC6B_REG       0xD4    /* Video n Coefficient Set C6B Register */
68 #define VNC6C_REG       0xD8    /* Video n Coefficient Set C6C Register */
69 #define VNC7A_REG       0xE0    /* Video n Coefficient Set C7A Register */
70 #define VNC7B_REG       0xE4    /* Video n Coefficient Set C7B Register */
71 #define VNC7C_REG       0xE8    /* Video n Coefficient Set C7C Register */
72 #define VNC8A_REG       0xF0    /* Video n Coefficient Set C8A Register */
73 #define VNC8B_REG       0xF4    /* Video n Coefficient Set C8B Register */
74 #define VNC8C_REG       0xF8    /* Video n Coefficient Set C8C Register */
75
76
77 /* Register bit fields for R-Car VIN */
78 /* Video n Main Control Register bits */
79 #define VNMC_FOC                (1 << 21)
80 #define VNMC_YCAL               (1 << 19)
81 #define VNMC_INF_YUV8_BT656     (0 << 16)
82 #define VNMC_INF_YUV8_BT601     (1 << 16)
83 #define VNMC_INF_YUV10_BT656    (2 << 16)
84 #define VNMC_INF_YUV10_BT601    (3 << 16)
85 #define VNMC_INF_YUV16          (5 << 16)
86 #define VNMC_INF_RGB888         (6 << 16)
87 #define VNMC_VUP                (1 << 10)
88 #define VNMC_IM_ODD             (0 << 3)
89 #define VNMC_IM_ODD_EVEN        (1 << 3)
90 #define VNMC_IM_EVEN            (2 << 3)
91 #define VNMC_IM_FULL            (3 << 3)
92 #define VNMC_BPS                (1 << 1)
93 #define VNMC_ME                 (1 << 0)
94
95 /* Video n Module Status Register bits */
96 #define VNMS_FBS_MASK           (3 << 3)
97 #define VNMS_FBS_SHIFT          3
98 #define VNMS_FS                 (1 << 2)
99 #define VNMS_AV                 (1 << 1)
100 #define VNMS_CA                 (1 << 0)
101
102 /* Video n Frame Capture Register bits */
103 #define VNFC_C_FRAME            (1 << 1)
104 #define VNFC_S_FRAME            (1 << 0)
105
106 /* Video n Interrupt Enable Register bits */
107 #define VNIE_FIE                (1 << 4)
108 #define VNIE_EFE                (1 << 1)
109
110 /* Video n Data Mode Register bits */
111 #define VNDMR_EXRGB             (1 << 8)
112 #define VNDMR_BPSM              (1 << 4)
113 #define VNDMR_DTMD_YCSEP        (1 << 1)
114 #define VNDMR_DTMD_ARGB1555     (1 << 0)
115
116 /* Video n Data Mode Register 2 bits */
117 #define VNDMR2_VPS              (1 << 30)
118 #define VNDMR2_HPS              (1 << 29)
119 #define VNDMR2_FTEV             (1 << 17)
120 #define VNDMR2_VLV(n)           ((n & 0xf) << 12)
121
122 static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
123 {
124         iowrite32(value, vin->base + offset);
125 }
126
127 static u32 rvin_read(struct rvin_dev *vin, u32 offset)
128 {
129         return ioread32(vin->base + offset);
130 }
131
132 static int rvin_setup(struct rvin_dev *vin)
133 {
134         u32 vnmc, dmr, dmr2, interrupts;
135         v4l2_std_id std;
136         bool progressive = false, output_is_yuv = false, input_is_yuv = false;
137
138         switch (vin->format.field) {
139         case V4L2_FIELD_TOP:
140                 vnmc = VNMC_IM_ODD;
141                 break;
142         case V4L2_FIELD_BOTTOM:
143                 vnmc = VNMC_IM_EVEN;
144                 break;
145         case V4L2_FIELD_INTERLACED:
146                 /* Default to TB */
147                 vnmc = VNMC_IM_FULL;
148                 /* Use BT if video standard can be read and is 60 Hz format */
149                 if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
150                         if (std & V4L2_STD_525_60)
151                                 vnmc = VNMC_IM_FULL | VNMC_FOC;
152                 }
153                 break;
154         case V4L2_FIELD_INTERLACED_TB:
155                 vnmc = VNMC_IM_FULL;
156                 break;
157         case V4L2_FIELD_INTERLACED_BT:
158                 vnmc = VNMC_IM_FULL | VNMC_FOC;
159                 break;
160         case V4L2_FIELD_ALTERNATE:
161         case V4L2_FIELD_NONE:
162                 if (vin->continuous) {
163                         vnmc = VNMC_IM_ODD_EVEN;
164                         progressive = true;
165                 } else {
166                         vnmc = VNMC_IM_ODD;
167                 }
168                 break;
169         default:
170                 vnmc = VNMC_IM_ODD;
171                 break;
172         }
173
174         /*
175          * Input interface
176          */
177         switch (vin->digital.code) {
178         case MEDIA_BUS_FMT_YUYV8_1X16:
179                 /* BT.601/BT.1358 16bit YCbCr422 */
180                 vnmc |= VNMC_INF_YUV16;
181                 input_is_yuv = true;
182                 break;
183         case MEDIA_BUS_FMT_UYVY8_2X8:
184                 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
185                 vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ?
186                         VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
187                 input_is_yuv = true;
188                 break;
189         case MEDIA_BUS_FMT_RGB888_1X24:
190                 vnmc |= VNMC_INF_RGB888;
191                 break;
192         case MEDIA_BUS_FMT_UYVY10_2X10:
193                 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
194                 vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ?
195                         VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
196                 input_is_yuv = true;
197                 break;
198         default:
199                 break;
200         }
201
202         /* Enable VSYNC Field Toogle mode after one VSYNC input */
203         dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
204
205         /* Hsync Signal Polarity Select */
206         if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
207                 dmr2 |= VNDMR2_HPS;
208
209         /* Vsync Signal Polarity Select */
210         if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
211                 dmr2 |= VNDMR2_VPS;
212
213         /*
214          * Output format
215          */
216         switch (vin->format.pixelformat) {
217         case V4L2_PIX_FMT_NV16:
218                 rvin_write(vin,
219                            ALIGN(vin->format.width * vin->format.height, 0x80),
220                            VNUVAOF_REG);
221                 dmr = VNDMR_DTMD_YCSEP;
222                 output_is_yuv = true;
223                 break;
224         case V4L2_PIX_FMT_YUYV:
225                 dmr = VNDMR_BPSM;
226                 output_is_yuv = true;
227                 break;
228         case V4L2_PIX_FMT_UYVY:
229                 dmr = 0;
230                 output_is_yuv = true;
231                 break;
232         case V4L2_PIX_FMT_XRGB555:
233                 dmr = VNDMR_DTMD_ARGB1555;
234                 break;
235         case V4L2_PIX_FMT_RGB565:
236                 dmr = 0;
237                 break;
238         case V4L2_PIX_FMT_XBGR32:
239                 /* Note: not supported on M1 */
240                 dmr = VNDMR_EXRGB;
241                 break;
242         default:
243                 vin_err(vin, "Invalid pixelformat (0x%x)\n",
244                         vin->format.pixelformat);
245                 return -EINVAL;
246         }
247
248         /* Always update on field change */
249         vnmc |= VNMC_VUP;
250
251         /* If input and output use the same colorspace, use bypass mode */
252         if (input_is_yuv == output_is_yuv)
253                 vnmc |= VNMC_BPS;
254
255         /* Progressive or interlaced mode */
256         interrupts = progressive ? VNIE_FIE : VNIE_EFE;
257
258         /* Ack interrupts */
259         rvin_write(vin, interrupts, VNINTS_REG);
260         /* Enable interrupts */
261         rvin_write(vin, interrupts, VNIE_REG);
262         /* Start capturing */
263         rvin_write(vin, dmr, VNDMR_REG);
264         rvin_write(vin, dmr2, VNDMR2_REG);
265
266         /* Enable module */
267         rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
268
269         return 0;
270 }
271
272 static void rvin_capture_on(struct rvin_dev *vin)
273 {
274         vin_dbg(vin, "Capture on in %s mode\n",
275                 vin->continuous ? "continuous" : "single");
276
277         if (vin->continuous)
278                 /* Continuous Frame Capture Mode */
279                 rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
280         else
281                 /* Single Frame Capture Mode */
282                 rvin_write(vin, VNFC_S_FRAME, VNFC_REG);
283 }
284
285 static void rvin_capture_off(struct rvin_dev *vin)
286 {
287         /* Set continuous & single transfer off */
288         rvin_write(vin, 0, VNFC_REG);
289 }
290
291 static int rvin_capture_start(struct rvin_dev *vin)
292 {
293         int ret;
294
295         rvin_crop_scale_comp(vin);
296
297         ret = rvin_setup(vin);
298         if (ret)
299                 return ret;
300
301         rvin_capture_on(vin);
302
303         return 0;
304 }
305
306 static void rvin_capture_stop(struct rvin_dev *vin)
307 {
308         rvin_capture_off(vin);
309
310         /* Disable module */
311         rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
312 }
313
314 static void rvin_disable_interrupts(struct rvin_dev *vin)
315 {
316         rvin_write(vin, 0, VNIE_REG);
317 }
318
319 static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
320 {
321         return rvin_read(vin, VNINTS_REG);
322 }
323
324 static void rvin_ack_interrupt(struct rvin_dev *vin)
325 {
326         rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
327 }
328
329 static bool rvin_capture_active(struct rvin_dev *vin)
330 {
331         return rvin_read(vin, VNMS_REG) & VNMS_CA;
332 }
333
334 static int rvin_get_active_slot(struct rvin_dev *vin, u32 vnms)
335 {
336         if (vin->continuous)
337                 return (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
338
339         return 0;
340 }
341
342 static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
343 {
344         if (vin->format.field == V4L2_FIELD_ALTERNATE) {
345                 /* If FS is set it's a Even field */
346                 if (vnms & VNMS_FS)
347                         return V4L2_FIELD_BOTTOM;
348                 return V4L2_FIELD_TOP;
349         }
350
351         return vin->format.field;
352 }
353
354 static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
355 {
356         const struct rvin_video_format *fmt;
357         int offsetx, offsety;
358         dma_addr_t offset;
359
360         fmt = rvin_format_from_pixel(vin->format.pixelformat);
361
362         /*
363          * There is no HW support for composition do the beast we can
364          * by modifying the buffer offset
365          */
366         offsetx = vin->compose.left * fmt->bpp;
367         offsety = vin->compose.top * vin->format.bytesperline;
368         offset = addr + offsetx + offsety;
369
370         /*
371          * The address needs to be 128 bytes aligned. Driver should never accept
372          * settings that do not satisfy this in the first place...
373          */
374         if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
375                 return;
376
377         rvin_write(vin, offset, VNMB_REG(slot));
378 }
379
380 /* -----------------------------------------------------------------------------
381  * Crop and Scaling Gen2
382  */
383
384 struct vin_coeff {
385         unsigned short xs_value;
386         u32 coeff_set[24];
387 };
388
389 static const struct vin_coeff vin_coeff_set[] = {
390         { 0x0000, {
391                           0x00000000, 0x00000000, 0x00000000,
392                           0x00000000, 0x00000000, 0x00000000,
393                           0x00000000, 0x00000000, 0x00000000,
394                           0x00000000, 0x00000000, 0x00000000,
395                           0x00000000, 0x00000000, 0x00000000,
396                           0x00000000, 0x00000000, 0x00000000,
397                           0x00000000, 0x00000000, 0x00000000,
398                           0x00000000, 0x00000000, 0x00000000 },
399         },
400         { 0x1000, {
401                           0x000fa400, 0x000fa400, 0x09625902,
402                           0x000003f8, 0x00000403, 0x3de0d9f0,
403                           0x001fffed, 0x00000804, 0x3cc1f9c3,
404                           0x001003de, 0x00000c01, 0x3cb34d7f,
405                           0x002003d2, 0x00000c00, 0x3d24a92d,
406                           0x00200bca, 0x00000bff, 0x3df600d2,
407                           0x002013cc, 0x000007ff, 0x3ed70c7e,
408                           0x00100fde, 0x00000000, 0x3f87c036 },
409         },
410         { 0x1200, {
411                           0x002ffff1, 0x002ffff1, 0x02a0a9c8,
412                           0x002003e7, 0x001ffffa, 0x000185bc,
413                           0x002007dc, 0x000003ff, 0x3e52859c,
414                           0x00200bd4, 0x00000002, 0x3d53996b,
415                           0x00100fd0, 0x00000403, 0x3d04ad2d,
416                           0x00000bd5, 0x00000403, 0x3d35ace7,
417                           0x3ff003e4, 0x00000801, 0x3dc674a1,
418                           0x3fffe800, 0x00000800, 0x3e76f461 },
419         },
420         { 0x1400, {
421                           0x00100be3, 0x00100be3, 0x04d1359a,
422                           0x00000fdb, 0x002003ed, 0x0211fd93,
423                           0x00000fd6, 0x002003f4, 0x0002d97b,
424                           0x000007d6, 0x002ffffb, 0x3e93b956,
425                           0x3ff003da, 0x001003ff, 0x3db49926,
426                           0x3fffefe9, 0x00100001, 0x3d655cee,
427                           0x3fffd400, 0x00000003, 0x3d65f4b6,
428                           0x000fb421, 0x00000402, 0x3dc6547e },
429         },
430         { 0x1600, {
431                           0x00000bdd, 0x00000bdd, 0x06519578,
432                           0x3ff007da, 0x00000be3, 0x03c24973,
433                           0x3ff003d9, 0x00000be9, 0x01b30d5f,
434                           0x3ffff7df, 0x001003f1, 0x0003c542,
435                           0x000fdfec, 0x001003f7, 0x3ec4711d,
436                           0x000fc400, 0x002ffffd, 0x3df504f1,
437                           0x001fa81a, 0x002ffc00, 0x3d957cc2,
438                           0x002f8c3c, 0x00100000, 0x3db5c891 },
439         },
440         { 0x1800, {
441                           0x3ff003dc, 0x3ff003dc, 0x0791e558,
442                           0x000ff7dd, 0x3ff007de, 0x05328554,
443                           0x000fe7e3, 0x3ff00be2, 0x03232546,
444                           0x000fd7ee, 0x000007e9, 0x0143bd30,
445                           0x001fb800, 0x000007ee, 0x00044511,
446                           0x002fa015, 0x000007f4, 0x3ef4bcee,
447                           0x002f8832, 0x001003f9, 0x3e4514c7,
448                           0x001f7853, 0x001003fd, 0x3de54c9f },
449         },
450         { 0x1a00, {
451                           0x000fefe0, 0x000fefe0, 0x08721d3c,
452                           0x001fdbe7, 0x000ffbde, 0x0652a139,
453                           0x001fcbf0, 0x000003df, 0x0463292e,
454                           0x002fb3ff, 0x3ff007e3, 0x0293a91d,
455                           0x002f9c12, 0x3ff00be7, 0x01241905,
456                           0x001f8c29, 0x000007ed, 0x3fe470eb,
457                           0x000f7c46, 0x000007f2, 0x3f04b8ca,
458                           0x3fef7865, 0x000007f6, 0x3e74e4a8 },
459         },
460         { 0x1c00, {
461                           0x001fd3e9, 0x001fd3e9, 0x08f23d26,
462                           0x002fbff3, 0x001fe3e4, 0x0712ad23,
463                           0x002fa800, 0x000ff3e0, 0x05631d1b,
464                           0x001f9810, 0x000ffbe1, 0x03b3890d,
465                           0x000f8c23, 0x000003e3, 0x0233e8fa,
466                           0x3fef843b, 0x000003e7, 0x00f430e4,
467                           0x3fbf8456, 0x3ff00bea, 0x00046cc8,
468                           0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
469         },
470         { 0x1e00, {
471                           0x001fbbf4, 0x001fbbf4, 0x09425112,
472                           0x001fa800, 0x002fc7ed, 0x0792b110,
473                           0x000f980e, 0x001fdbe6, 0x0613110a,
474                           0x3fff8c20, 0x001fe7e3, 0x04a368fd,
475                           0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
476                           0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
477                           0x3f5f9c61, 0x000003e6, 0x00e428c5,
478                           0x3f1fb07b, 0x000003eb, 0x3fe440af },
479         },
480         { 0x2000, {
481                           0x000fa400, 0x000fa400, 0x09625902,
482                           0x3fff980c, 0x001fb7f5, 0x0812b0ff,
483                           0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
484                           0x3faf902d, 0x001fd3e8, 0x055348f1,
485                           0x3f7f983f, 0x001fe3e5, 0x04038ce3,
486                           0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
487                           0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
488                           0x3ecfd880, 0x000fffe6, 0x00c404ac },
489         },
490         { 0x2200, {
491                           0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
492                           0x3fbf9818, 0x3fffa400, 0x0842a8f1,
493                           0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
494                           0x3f5fa037, 0x000fc3ef, 0x05d330e4,
495                           0x3f2fac49, 0x001fcfea, 0x04a364d9,
496                           0x3effc05c, 0x001fdbe7, 0x038394ca,
497                           0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
498                           0x3ea00083, 0x001fefe6, 0x0183c0a9 },
499         },
500         { 0x2400, {
501                           0x3f9fa014, 0x3f9fa014, 0x098260e6,
502                           0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
503                           0x3f4fa431, 0x3fefa400, 0x0742d8e1,
504                           0x3f1fb440, 0x3fffb3f8, 0x062310d9,
505                           0x3eefc850, 0x000fbbf2, 0x050340d0,
506                           0x3ecfe062, 0x000fcbec, 0x041364c2,
507                           0x3ea00073, 0x001fd3ea, 0x03037cb5,
508                           0x3e902086, 0x001fdfe8, 0x022388a5 },
509         },
510         { 0x2600, {
511                           0x3f5fa81e, 0x3f5fa81e, 0x096258da,
512                           0x3f3fac2b, 0x3f8fa412, 0x088290d8,
513                           0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
514                           0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
515                           0x3ecfe456, 0x3fefaffa, 0x05531cc6,
516                           0x3eb00066, 0x3fffbbf3, 0x047334bb,
517                           0x3ea01c77, 0x000fc7ee, 0x039348ae,
518                           0x3ea04486, 0x000fd3eb, 0x02b350a1 },
519         },
520         { 0x2800, {
521                           0x3f2fb426, 0x3f2fb426, 0x094250ce,
522                           0x3f0fc032, 0x3f4fac1b, 0x086284cd,
523                           0x3eefd040, 0x3f7fa811, 0x0782acc9,
524                           0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
525                           0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
526                           0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
527                           0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
528                           0x3ec06884, 0x000fbff2, 0x03031c9e },
529         },
530         { 0x2a00, {
531                           0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
532                           0x3eefd439, 0x3f2fb822, 0x08526cc2,
533                           0x3edfe845, 0x3f4fb018, 0x078294bf,
534                           0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
535                           0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
536                           0x3ec0386b, 0x3fafac00, 0x0502e8ac,
537                           0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
538                           0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
539         },
540         { 0x2c00, {
541                           0x3eefdc31, 0x3eefdc31, 0x08e238b8,
542                           0x3edfec3d, 0x3f0fc828, 0x082258b9,
543                           0x3ed00049, 0x3f1fc01e, 0x077278b6,
544                           0x3ed01455, 0x3f3fb815, 0x06c294b2,
545                           0x3ed03460, 0x3f5fb40d, 0x0602acac,
546                           0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
547                           0x3f107476, 0x3f9fb400, 0x0472c89d,
548                           0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
549         },
550         { 0x2e00, {
551                           0x3eefec37, 0x3eefec37, 0x088220b0,
552                           0x3ee00041, 0x3effdc2d, 0x07f244ae,
553                           0x3ee0144c, 0x3f0fd023, 0x07625cad,
554                           0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
555                           0x3f004861, 0x3f3fbc13, 0x060288a6,
556                           0x3f20686b, 0x3f5fb80c, 0x05529c9e,
557                           0x3f408c74, 0x3f6fb805, 0x04b2ac96,
558                           0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
559         },
560         { 0x3000, {
561                           0x3ef0003a, 0x3ef0003a, 0x084210a6,
562                           0x3ef01045, 0x3effec32, 0x07b228a7,
563                           0x3f00284e, 0x3f0fdc29, 0x073244a4,
564                           0x3f104058, 0x3f0fd420, 0x06a258a2,
565                           0x3f305c62, 0x3f2fc818, 0x0612689d,
566                           0x3f508069, 0x3f3fc011, 0x05728496,
567                           0x3f80a072, 0x3f4fc00a, 0x04d28c90,
568                           0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
569         },
570         { 0x3200, {
571                           0x3f00103e, 0x3f00103e, 0x07f1fc9e,
572                           0x3f102447, 0x3f000035, 0x0782149d,
573                           0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
574                           0x3f405458, 0x3f0fe424, 0x06924099,
575                           0x3f607061, 0x3f1fd41d, 0x06024c97,
576                           0x3f909068, 0x3f2fcc16, 0x05726490,
577                           0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
578                           0x0000d077, 0x3f4fc409, 0x04627484 },
579         },
580         { 0x3400, {
581                           0x3f202040, 0x3f202040, 0x07a1e898,
582                           0x3f303449, 0x3f100c38, 0x0741fc98,
583                           0x3f504c50, 0x3f10002f, 0x06e21495,
584                           0x3f706459, 0x3f1ff028, 0x06722492,
585                           0x3fa08060, 0x3f1fe421, 0x05f2348f,
586                           0x3fd09c67, 0x3f1fdc19, 0x05824c89,
587                           0x0000bc6e, 0x3f2fd014, 0x04f25086,
588                           0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
589         },
590         { 0x3600, {
591                           0x3f403042, 0x3f403042, 0x0761d890,
592                           0x3f504848, 0x3f301c3b, 0x0701f090,
593                           0x3f805c50, 0x3f200c33, 0x06a2008f,
594                           0x3fa07458, 0x3f10002b, 0x06520c8d,
595                           0x3fd0905e, 0x3f1ff424, 0x05e22089,
596                           0x0000ac65, 0x3f1fe81d, 0x05823483,
597                           0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
598                           0x0080e871, 0x3f2fd412, 0x0482407c },
599         },
600         { 0x3800, {
601                           0x3f604043, 0x3f604043, 0x0721c88a,
602                           0x3f80544a, 0x3f502c3c, 0x06d1d88a,
603                           0x3fb06851, 0x3f301c35, 0x0681e889,
604                           0x3fd08456, 0x3f30082f, 0x0611fc88,
605                           0x00009c5d, 0x3f200027, 0x05d20884,
606                           0x0030b863, 0x3f2ff421, 0x05621880,
607                           0x0070d468, 0x3f2fe81b, 0x0502247c,
608                           0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
609         },
610         { 0x3a00, {
611                           0x3f904c44, 0x3f904c44, 0x06e1b884,
612                           0x3fb0604a, 0x3f70383e, 0x0691c885,
613                           0x3fe07451, 0x3f502c36, 0x0661d483,
614                           0x00009055, 0x3f401831, 0x0601ec81,
615                           0x0030a85b, 0x3f300c2a, 0x05b1f480,
616                           0x0070c061, 0x3f300024, 0x0562047a,
617                           0x00b0d867, 0x3f3ff41e, 0x05020c77,
618                           0x00f0f46b, 0x3f2fec19, 0x04a21474 },
619         },
620         { 0x3c00, {
621                           0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
622                           0x3fe06c4b, 0x3f902c3f, 0x0681c081,
623                           0x0000844f, 0x3f703838, 0x0631cc7d,
624                           0x00309855, 0x3f602433, 0x05d1d47e,
625                           0x0060b459, 0x3f50142e, 0x0581e47b,
626                           0x00a0c85f, 0x3f400828, 0x0531f078,
627                           0x00e0e064, 0x3f300021, 0x0501fc73,
628                           0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
629         },
630         { 0x3e00, {
631                           0x3fe06444, 0x3fe06444, 0x0681a07a,
632                           0x00007849, 0x3fc0503f, 0x0641b07a,
633                           0x0020904d, 0x3fa0403a, 0x05f1c07a,
634                           0x0060a453, 0x3f803034, 0x05c1c878,
635                           0x0090b858, 0x3f70202f, 0x0571d477,
636                           0x00d0d05d, 0x3f501829, 0x0531e073,
637                           0x0110e462, 0x3f500825, 0x04e1e471,
638                           0x01510065, 0x3f40001f, 0x04a1f06d },
639         },
640         { 0x4000, {
641                           0x00007044, 0x00007044, 0x06519476,
642                           0x00208448, 0x3fe05c3f, 0x0621a476,
643                           0x0050984d, 0x3fc04c3a, 0x05e1b075,
644                           0x0080ac52, 0x3fa03c35, 0x05a1b875,
645                           0x00c0c056, 0x3f803030, 0x0561c473,
646                           0x0100d45b, 0x3f70202b, 0x0521d46f,
647                           0x0140e860, 0x3f601427, 0x04d1d46e,
648                           0x01810064, 0x3f500822, 0x0491dc6b },
649         },
650         { 0x5000, {
651                           0x0110a442, 0x0110a442, 0x0551545e,
652                           0x0140b045, 0x00e0983f, 0x0531585f,
653                           0x0160c047, 0x00c08c3c, 0x0511645e,
654                           0x0190cc4a, 0x00908039, 0x04f1685f,
655                           0x01c0dc4c, 0x00707436, 0x04d1705e,
656                           0x0200e850, 0x00506833, 0x04b1785b,
657                           0x0230f453, 0x00305c30, 0x0491805a,
658                           0x02710056, 0x0010542d, 0x04718059 },
659         },
660         { 0x6000, {
661                           0x01c0bc40, 0x01c0bc40, 0x04c13052,
662                           0x01e0c841, 0x01a0b43d, 0x04c13851,
663                           0x0210cc44, 0x0180a83c, 0x04a13453,
664                           0x0230d845, 0x0160a03a, 0x04913c52,
665                           0x0260e047, 0x01409838, 0x04714052,
666                           0x0280ec49, 0x01208c37, 0x04514c50,
667                           0x02b0f44b, 0x01008435, 0x04414c50,
668                           0x02d1004c, 0x00e07c33, 0x0431544f },
669         },
670         { 0x7000, {
671                           0x0230c83e, 0x0230c83e, 0x04711c4c,
672                           0x0250d03f, 0x0210c43c, 0x0471204b,
673                           0x0270d840, 0x0200b83c, 0x0451244b,
674                           0x0290dc42, 0x01e0b43a, 0x0441244c,
675                           0x02b0e443, 0x01c0b038, 0x0441284b,
676                           0x02d0ec44, 0x01b0a438, 0x0421304a,
677                           0x02f0f445, 0x0190a036, 0x04213449,
678                           0x0310f847, 0x01709c34, 0x04213848 },
679         },
680         { 0x8000, {
681                           0x0280d03d, 0x0280d03d, 0x04310c48,
682                           0x02a0d43e, 0x0270c83c, 0x04311047,
683                           0x02b0dc3e, 0x0250c83a, 0x04311447,
684                           0x02d0e040, 0x0240c03a, 0x04211446,
685                           0x02e0e840, 0x0220bc39, 0x04111847,
686                           0x0300e842, 0x0210b438, 0x04012445,
687                           0x0310f043, 0x0200b037, 0x04012045,
688                           0x0330f444, 0x01e0ac36, 0x03f12445 },
689         },
690         { 0xefff, {
691                           0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
692                           0x0340e03a, 0x0330e039, 0x03c0f03e,
693                           0x0350e03b, 0x0330dc39, 0x03c0ec3e,
694                           0x0350e43a, 0x0320dc38, 0x03c0f43e,
695                           0x0360e43b, 0x0320d839, 0x03b0f03e,
696                           0x0360e83b, 0x0310d838, 0x03c0fc3b,
697                           0x0370e83b, 0x0310d439, 0x03a0f83d,
698                           0x0370e83c, 0x0300d438, 0x03b0fc3c },
699         }
700 };
701
702 static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
703 {
704         int i;
705         const struct vin_coeff *p_prev_set = NULL;
706         const struct vin_coeff *p_set = NULL;
707
708         /* Look for suitable coefficient values */
709         for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
710                 p_prev_set = p_set;
711                 p_set = &vin_coeff_set[i];
712
713                 if (xs < p_set->xs_value)
714                         break;
715         }
716
717         /* Use previous value if its XS value is closer */
718         if (p_prev_set && p_set &&
719             xs - p_prev_set->xs_value < p_set->xs_value - xs)
720                 p_set = p_prev_set;
721
722         /* Set coefficient registers */
723         rvin_write(vin, p_set->coeff_set[0], VNC1A_REG);
724         rvin_write(vin, p_set->coeff_set[1], VNC1B_REG);
725         rvin_write(vin, p_set->coeff_set[2], VNC1C_REG);
726
727         rvin_write(vin, p_set->coeff_set[3], VNC2A_REG);
728         rvin_write(vin, p_set->coeff_set[4], VNC2B_REG);
729         rvin_write(vin, p_set->coeff_set[5], VNC2C_REG);
730
731         rvin_write(vin, p_set->coeff_set[6], VNC3A_REG);
732         rvin_write(vin, p_set->coeff_set[7], VNC3B_REG);
733         rvin_write(vin, p_set->coeff_set[8], VNC3C_REG);
734
735         rvin_write(vin, p_set->coeff_set[9], VNC4A_REG);
736         rvin_write(vin, p_set->coeff_set[10], VNC4B_REG);
737         rvin_write(vin, p_set->coeff_set[11], VNC4C_REG);
738
739         rvin_write(vin, p_set->coeff_set[12], VNC5A_REG);
740         rvin_write(vin, p_set->coeff_set[13], VNC5B_REG);
741         rvin_write(vin, p_set->coeff_set[14], VNC5C_REG);
742
743         rvin_write(vin, p_set->coeff_set[15], VNC6A_REG);
744         rvin_write(vin, p_set->coeff_set[16], VNC6B_REG);
745         rvin_write(vin, p_set->coeff_set[17], VNC6C_REG);
746
747         rvin_write(vin, p_set->coeff_set[18], VNC7A_REG);
748         rvin_write(vin, p_set->coeff_set[19], VNC7B_REG);
749         rvin_write(vin, p_set->coeff_set[20], VNC7C_REG);
750
751         rvin_write(vin, p_set->coeff_set[21], VNC8A_REG);
752         rvin_write(vin, p_set->coeff_set[22], VNC8B_REG);
753         rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
754 }
755
756 void rvin_crop_scale_comp(struct rvin_dev *vin)
757 {
758         u32 xs, ys;
759
760         /* Set Start/End Pixel/Line Pre-Clip */
761         rvin_write(vin, vin->crop.left, VNSPPRC_REG);
762         rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
763         switch (vin->format.field) {
764         case V4L2_FIELD_INTERLACED:
765         case V4L2_FIELD_INTERLACED_TB:
766         case V4L2_FIELD_INTERLACED_BT:
767                 rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG);
768                 rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1,
769                            VNELPRC_REG);
770                 break;
771         default:
772                 rvin_write(vin, vin->crop.top, VNSLPRC_REG);
773                 rvin_write(vin, vin->crop.top + vin->crop.height - 1,
774                            VNELPRC_REG);
775                 break;
776         }
777
778         /* Set scaling coefficient */
779         ys = 0;
780         if (vin->crop.height != vin->compose.height)
781                 ys = (4096 * vin->crop.height) / vin->compose.height;
782         rvin_write(vin, ys, VNYS_REG);
783
784         xs = 0;
785         if (vin->crop.width != vin->compose.width)
786                 xs = (4096 * vin->crop.width) / vin->compose.width;
787
788         /* Horizontal upscaling is up to double size */
789         if (xs > 0 && xs < 2048)
790                 xs = 2048;
791
792         rvin_write(vin, xs, VNXS_REG);
793
794         /* Horizontal upscaling is done out by scaling down from double size */
795         if (xs < 4096)
796                 xs *= 2;
797
798         rvin_set_coeff(vin, xs);
799
800         /* Set Start/End Pixel/Line Post-Clip */
801         rvin_write(vin, 0, VNSPPOC_REG);
802         rvin_write(vin, 0, VNSLPOC_REG);
803         rvin_write(vin, vin->format.width - 1, VNEPPOC_REG);
804         switch (vin->format.field) {
805         case V4L2_FIELD_INTERLACED:
806         case V4L2_FIELD_INTERLACED_TB:
807         case V4L2_FIELD_INTERLACED_BT:
808                 rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG);
809                 break;
810         default:
811                 rvin_write(vin, vin->format.height - 1, VNELPOC_REG);
812                 break;
813         }
814
815         if (vin->format.pixelformat == V4L2_PIX_FMT_NV16)
816                 rvin_write(vin, ALIGN(vin->format.width, 0x20), VNIS_REG);
817         else
818                 rvin_write(vin, ALIGN(vin->format.width, 0x10), VNIS_REG);
819
820         vin_dbg(vin,
821                 "Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n",
822                 vin->crop.width, vin->crop.height, vin->crop.left,
823                 vin->crop.top, ys, xs, vin->format.width, vin->format.height,
824                 0, 0);
825 }
826
827 void rvin_scale_try(struct rvin_dev *vin, struct v4l2_pix_format *pix,
828                     u32 width, u32 height)
829 {
830         /* All VIN channels on Gen2 have scalers */
831         pix->width = width;
832         pix->height = height;
833 }
834
835 /* -----------------------------------------------------------------------------
836  * DMA Functions
837  */
838
839 #define RVIN_TIMEOUT_MS 100
840 #define RVIN_RETRIES 10
841
842 struct rvin_buffer {
843         struct vb2_v4l2_buffer vb;
844         struct list_head list;
845 };
846
847 #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
848                                                struct rvin_buffer, \
849                                                vb)->list)
850
851 /* Moves a buffer from the queue to the HW slots */
852 static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
853 {
854         struct rvin_buffer *buf;
855         struct vb2_v4l2_buffer *vbuf;
856         dma_addr_t phys_addr_top;
857
858         if (vin->queue_buf[slot] != NULL)
859                 return true;
860
861         if (list_empty(&vin->buf_list))
862                 return false;
863
864         vin_dbg(vin, "Filling HW slot: %d\n", slot);
865
866         /* Keep track of buffer we give to HW */
867         buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
868         vbuf = &buf->vb;
869         list_del_init(to_buf_list(vbuf));
870         vin->queue_buf[slot] = vbuf;
871
872         /* Setup DMA */
873         phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
874         rvin_set_slot_addr(vin, slot, phys_addr_top);
875
876         return true;
877 }
878
879 static bool rvin_fill_hw(struct rvin_dev *vin)
880 {
881         int slot, limit;
882
883         limit = vin->continuous ? HW_BUFFER_NUM : 1;
884
885         for (slot = 0; slot < limit; slot++)
886                 if (!rvin_fill_hw_slot(vin, slot))
887                         return false;
888         return true;
889 }
890
891 static irqreturn_t rvin_irq(int irq, void *data)
892 {
893         struct rvin_dev *vin = data;
894         u32 int_status, vnms;
895         int slot;
896         unsigned int sequence, handled = 0;
897         unsigned long flags;
898
899         spin_lock_irqsave(&vin->qlock, flags);
900
901         int_status = rvin_get_interrupt_status(vin);
902         if (!int_status)
903                 goto done;
904
905         rvin_ack_interrupt(vin);
906         handled = 1;
907
908         /* Nothing to do if capture status is 'STOPPED' */
909         if (vin->state == STOPPED) {
910                 vin_dbg(vin, "IRQ while state stopped\n");
911                 goto done;
912         }
913
914         /* Nothing to do if capture status is 'STOPPING' */
915         if (vin->state == STOPPING) {
916                 vin_dbg(vin, "IRQ while state stopping\n");
917                 goto done;
918         }
919
920         /* Prepare for capture and update state */
921         vnms = rvin_read(vin, VNMS_REG);
922         slot = rvin_get_active_slot(vin, vnms);
923         sequence = vin->sequence++;
924
925         vin_dbg(vin, "IRQ %02d: %d\tbuf0: %c buf1: %c buf2: %c\tmore: %d\n",
926                 sequence, slot,
927                 slot == 0 ? 'x' : vin->queue_buf[0] != NULL ? '1' : '0',
928                 slot == 1 ? 'x' : vin->queue_buf[1] != NULL ? '1' : '0',
929                 slot == 2 ? 'x' : vin->queue_buf[2] != NULL ? '1' : '0',
930                 !list_empty(&vin->buf_list));
931
932         /* HW have written to a slot that is not prepared we are in trouble */
933         if (WARN_ON((vin->queue_buf[slot] == NULL)))
934                 goto done;
935
936         /* Capture frame */
937         vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
938         vin->queue_buf[slot]->sequence = sequence;
939         vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
940         vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
941         vin->queue_buf[slot] = NULL;
942
943         /* Prepare for next frame */
944         if (!rvin_fill_hw(vin)) {
945
946                 /*
947                  * Can't supply HW with new buffers fast enough. Halt
948                  * capture until more buffers are available.
949                  */
950                 vin->state = STALLED;
951
952                 /*
953                  * The continuous capturing requires an explicit stop
954                  * operation when there is no buffer to be set into
955                  * the VnMBm registers.
956                  */
957                 if (vin->continuous) {
958                         rvin_capture_off(vin);
959                         vin_dbg(vin, "IRQ %02d: hw not ready stop\n", sequence);
960                 }
961         } else {
962                 /*
963                  * The single capturing requires an explicit capture
964                  * operation to fetch the next frame.
965                  */
966                 if (!vin->continuous)
967                         rvin_capture_on(vin);
968         }
969 done:
970         spin_unlock_irqrestore(&vin->qlock, flags);
971
972         return IRQ_RETVAL(handled);
973 }
974
975 /* Need to hold qlock before calling */
976 static void return_all_buffers(struct rvin_dev *vin,
977                                enum vb2_buffer_state state)
978 {
979         struct rvin_buffer *buf, *node;
980         int i;
981
982         for (i = 0; i < HW_BUFFER_NUM; i++) {
983                 if (vin->queue_buf[i]) {
984                         vb2_buffer_done(&vin->queue_buf[i]->vb2_buf,
985                                         state);
986                         vin->queue_buf[i] = NULL;
987                 }
988         }
989
990         list_for_each_entry_safe(buf, node, &vin->buf_list, list) {
991                 vb2_buffer_done(&buf->vb.vb2_buf, state);
992                 list_del(&buf->list);
993         }
994 }
995
996 static int rvin_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
997                             unsigned int *nplanes, unsigned int sizes[],
998                             struct device *alloc_devs[])
999
1000 {
1001         struct rvin_dev *vin = vb2_get_drv_priv(vq);
1002
1003         /* Make sure the image size is large enough. */
1004         if (*nplanes)
1005                 return sizes[0] < vin->format.sizeimage ? -EINVAL : 0;
1006
1007         *nplanes = 1;
1008         sizes[0] = vin->format.sizeimage;
1009
1010         return 0;
1011 };
1012
1013 static int rvin_buffer_prepare(struct vb2_buffer *vb)
1014 {
1015         struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1016         unsigned long size = vin->format.sizeimage;
1017
1018         if (vb2_plane_size(vb, 0) < size) {
1019                 vin_err(vin, "buffer too small (%lu < %lu)\n",
1020                         vb2_plane_size(vb, 0), size);
1021                 return -EINVAL;
1022         }
1023
1024         vb2_set_plane_payload(vb, 0, size);
1025
1026         return 0;
1027 }
1028
1029 static void rvin_buffer_queue(struct vb2_buffer *vb)
1030 {
1031         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1032         struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1033         unsigned long flags;
1034
1035         spin_lock_irqsave(&vin->qlock, flags);
1036
1037         list_add_tail(to_buf_list(vbuf), &vin->buf_list);
1038
1039         /*
1040          * If capture is stalled add buffer to HW and restart
1041          * capturing if HW is ready to continue.
1042          */
1043         if (vin->state == STALLED)
1044                 if (rvin_fill_hw(vin))
1045                         rvin_capture_on(vin);
1046
1047         spin_unlock_irqrestore(&vin->qlock, flags);
1048 }
1049
1050 static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
1051 {
1052         struct rvin_dev *vin = vb2_get_drv_priv(vq);
1053         struct v4l2_subdev *sd;
1054         unsigned long flags;
1055         int ret;
1056
1057         sd = vin_to_source(vin);
1058         v4l2_subdev_call(sd, video, s_stream, 1);
1059
1060         spin_lock_irqsave(&vin->qlock, flags);
1061
1062         vin->state = RUNNING;
1063         vin->sequence = 0;
1064
1065         /* Continuous capture requires more buffers then there are HW slots */
1066         vin->continuous = count > HW_BUFFER_NUM;
1067
1068         /*
1069          * This should never happen but if we don't have enough
1070          * buffers for HW bail out
1071          */
1072         if (!rvin_fill_hw(vin)) {
1073                 vin_err(vin, "HW not ready to start, not enough buffers available\n");
1074                 ret = -EINVAL;
1075                 goto out;
1076         }
1077
1078         ret = rvin_capture_start(vin);
1079 out:
1080         /* Return all buffers if something went wrong */
1081         if (ret) {
1082                 return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
1083                 v4l2_subdev_call(sd, video, s_stream, 0);
1084         }
1085
1086         spin_unlock_irqrestore(&vin->qlock, flags);
1087
1088         return ret;
1089 }
1090
1091 static void rvin_stop_streaming(struct vb2_queue *vq)
1092 {
1093         struct rvin_dev *vin = vb2_get_drv_priv(vq);
1094         struct v4l2_subdev *sd;
1095         unsigned long flags;
1096         int retries = 0;
1097
1098         spin_lock_irqsave(&vin->qlock, flags);
1099
1100         vin->state = STOPPING;
1101
1102         /* Wait for streaming to stop */
1103         while (retries++ < RVIN_RETRIES) {
1104
1105                 rvin_capture_stop(vin);
1106
1107                 /* Check if HW is stopped */
1108                 if (!rvin_capture_active(vin)) {
1109                         vin->state = STOPPED;
1110                         break;
1111                 }
1112
1113                 spin_unlock_irqrestore(&vin->qlock, flags);
1114                 msleep(RVIN_TIMEOUT_MS);
1115                 spin_lock_irqsave(&vin->qlock, flags);
1116         }
1117
1118         if (vin->state != STOPPED) {
1119                 /*
1120                  * If this happens something have gone horribly wrong.
1121                  * Set state to stopped to prevent the interrupt handler
1122                  * to make things worse...
1123                  */
1124                 vin_err(vin, "Failed stop HW, something is seriously broken\n");
1125                 vin->state = STOPPED;
1126         }
1127
1128         /* Release all active buffers */
1129         return_all_buffers(vin, VB2_BUF_STATE_ERROR);
1130
1131         spin_unlock_irqrestore(&vin->qlock, flags);
1132
1133         sd = vin_to_source(vin);
1134         v4l2_subdev_call(sd, video, s_stream, 0);
1135
1136         /* disable interrupts */
1137         rvin_disable_interrupts(vin);
1138 }
1139
1140 static const struct vb2_ops rvin_qops = {
1141         .queue_setup            = rvin_queue_setup,
1142         .buf_prepare            = rvin_buffer_prepare,
1143         .buf_queue              = rvin_buffer_queue,
1144         .start_streaming        = rvin_start_streaming,
1145         .stop_streaming         = rvin_stop_streaming,
1146         .wait_prepare           = vb2_ops_wait_prepare,
1147         .wait_finish            = vb2_ops_wait_finish,
1148 };
1149
1150 void rvin_dma_remove(struct rvin_dev *vin)
1151 {
1152         mutex_destroy(&vin->lock);
1153
1154         v4l2_device_unregister(&vin->v4l2_dev);
1155 }
1156
1157 int rvin_dma_probe(struct rvin_dev *vin, int irq)
1158 {
1159         struct vb2_queue *q = &vin->queue;
1160         int i, ret;
1161
1162         /* Initialize the top-level structure */
1163         ret = v4l2_device_register(vin->dev, &vin->v4l2_dev);
1164         if (ret)
1165                 return ret;
1166
1167         mutex_init(&vin->lock);
1168         INIT_LIST_HEAD(&vin->buf_list);
1169
1170         spin_lock_init(&vin->qlock);
1171
1172         vin->state = STOPPED;
1173
1174         for (i = 0; i < HW_BUFFER_NUM; i++)
1175                 vin->queue_buf[i] = NULL;
1176
1177         /* buffer queue */
1178         q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1179         q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1180         q->lock = &vin->lock;
1181         q->drv_priv = vin;
1182         q->buf_struct_size = sizeof(struct rvin_buffer);
1183         q->ops = &rvin_qops;
1184         q->mem_ops = &vb2_dma_contig_memops;
1185         q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1186         q->min_buffers_needed = 2;
1187         q->dev = vin->dev;
1188
1189         ret = vb2_queue_init(q);
1190         if (ret < 0) {
1191                 vin_err(vin, "failed to initialize VB2 queue\n");
1192                 goto error;
1193         }
1194
1195         /* irq */
1196         ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED,
1197                                KBUILD_MODNAME, vin);
1198         if (ret) {
1199                 vin_err(vin, "failed to request irq\n");
1200                 goto error;
1201         }
1202
1203         return 0;
1204 error:
1205         rvin_dma_remove(vin);
1206
1207         return ret;
1208 }