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