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