2 * SoC-camera host driver for Renesas R-Car VIN unit
4 * Copyright (C) 2011-2013 Renesas Solutions Corp.
5 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
7 * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c"
9 * Copyright (C) 2008 Magnus Damm
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.
17 #include <linux/delay.h>
18 #include <linux/interrupt.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
23 #include <linux/of_device.h>
24 #include <linux/platform_data/camera-rcar.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/slab.h>
28 #include <linux/videodev2.h>
30 #include <media/soc_camera.h>
31 #include <media/soc_mediabus.h>
32 #include <media/v4l2-common.h>
33 #include <media/v4l2-dev.h>
34 #include <media/v4l2-device.h>
35 #include <media/v4l2-mediabus.h>
36 #include <media/v4l2-of.h>
37 #include <media/v4l2-subdev.h>
38 #include <media/videobuf2-dma-contig.h>
40 #include "soc_scale_crop.h"
42 #define DRV_NAME "rcar_vin"
44 /* Register offsets for R-Car VIN */
45 #define VNMC_REG 0x00 /* Video n Main Control Register */
46 #define VNMS_REG 0x04 /* Video n Module Status Register */
47 #define VNFC_REG 0x08 /* Video n Frame Capture Register */
48 #define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */
49 #define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */
50 #define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */
51 #define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */
52 #define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */
53 #define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */
54 #define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */
55 #define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */
56 #define VNIS_REG 0x2C /* Video n Image Stride Register */
57 #define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
58 #define VNIE_REG 0x40 /* Video n Interrupt Enable Register */
59 #define VNINTS_REG 0x44 /* Video n Interrupt Status Register */
60 #define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */
61 #define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */
62 #define VNYS_REG 0x50 /* Video n Y Scale Register */
63 #define VNXS_REG 0x54 /* Video n X Scale Register */
64 #define VNDMR_REG 0x58 /* Video n Data Mode Register */
65 #define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */
66 #define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */
67 #define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */
68 #define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */
69 #define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */
70 #define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */
71 #define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */
72 #define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */
73 #define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */
74 #define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */
75 #define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */
76 #define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */
77 #define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */
78 #define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */
79 #define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */
80 #define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */
81 #define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */
82 #define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */
83 #define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */
84 #define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */
85 #define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */
86 #define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */
87 #define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */
88 #define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */
89 #define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */
90 #define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */
92 /* Register bit fields for R-Car VIN */
93 /* Video n Main Control Register bits */
94 #define VNMC_FOC (1 << 21)
95 #define VNMC_YCAL (1 << 19)
96 #define VNMC_INF_YUV8_BT656 (0 << 16)
97 #define VNMC_INF_YUV8_BT601 (1 << 16)
98 #define VNMC_INF_YUV10_BT656 (2 << 16)
99 #define VNMC_INF_YUV10_BT601 (3 << 16)
100 #define VNMC_INF_YUV16 (5 << 16)
101 #define VNMC_VUP (1 << 10)
102 #define VNMC_IM_ODD (0 << 3)
103 #define VNMC_IM_ODD_EVEN (1 << 3)
104 #define VNMC_IM_EVEN (2 << 3)
105 #define VNMC_IM_FULL (3 << 3)
106 #define VNMC_BPS (1 << 1)
107 #define VNMC_ME (1 << 0)
109 /* Video n Module Status Register bits */
110 #define VNMS_FBS_MASK (3 << 3)
111 #define VNMS_FBS_SHIFT 3
112 #define VNMS_AV (1 << 1)
113 #define VNMS_CA (1 << 0)
115 /* Video n Frame Capture Register bits */
116 #define VNFC_C_FRAME (1 << 1)
117 #define VNFC_S_FRAME (1 << 0)
119 /* Video n Interrupt Enable Register bits */
120 #define VNIE_FIE (1 << 4)
121 #define VNIE_EFE (1 << 1)
123 /* Video n Data Mode Register bits */
124 #define VNDMR_EXRGB (1 << 8)
125 #define VNDMR_BPSM (1 << 4)
126 #define VNDMR_DTMD_YCSEP (1 << 1)
127 #define VNDMR_DTMD_ARGB1555 (1 << 0)
129 /* Video n Data Mode Register 2 bits */
130 #define VNDMR2_VPS (1 << 30)
131 #define VNDMR2_HPS (1 << 29)
132 #define VNDMR2_FTEV (1 << 17)
133 #define VNDMR2_VLV(n) ((n & 0xf) << 12)
135 #define VIN_MAX_WIDTH 2048
136 #define VIN_MAX_HEIGHT 2048
138 #define TIMEOUT_MS 100
148 unsigned short xs_value;
152 static const struct vin_coeff vin_coeff_set[] = {
154 0x00000000, 0x00000000, 0x00000000,
155 0x00000000, 0x00000000, 0x00000000,
156 0x00000000, 0x00000000, 0x00000000,
157 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000 },
164 0x000fa400, 0x000fa400, 0x09625902,
165 0x000003f8, 0x00000403, 0x3de0d9f0,
166 0x001fffed, 0x00000804, 0x3cc1f9c3,
167 0x001003de, 0x00000c01, 0x3cb34d7f,
168 0x002003d2, 0x00000c00, 0x3d24a92d,
169 0x00200bca, 0x00000bff, 0x3df600d2,
170 0x002013cc, 0x000007ff, 0x3ed70c7e,
171 0x00100fde, 0x00000000, 0x3f87c036 },
174 0x002ffff1, 0x002ffff1, 0x02a0a9c8,
175 0x002003e7, 0x001ffffa, 0x000185bc,
176 0x002007dc, 0x000003ff, 0x3e52859c,
177 0x00200bd4, 0x00000002, 0x3d53996b,
178 0x00100fd0, 0x00000403, 0x3d04ad2d,
179 0x00000bd5, 0x00000403, 0x3d35ace7,
180 0x3ff003e4, 0x00000801, 0x3dc674a1,
181 0x3fffe800, 0x00000800, 0x3e76f461 },
184 0x00100be3, 0x00100be3, 0x04d1359a,
185 0x00000fdb, 0x002003ed, 0x0211fd93,
186 0x00000fd6, 0x002003f4, 0x0002d97b,
187 0x000007d6, 0x002ffffb, 0x3e93b956,
188 0x3ff003da, 0x001003ff, 0x3db49926,
189 0x3fffefe9, 0x00100001, 0x3d655cee,
190 0x3fffd400, 0x00000003, 0x3d65f4b6,
191 0x000fb421, 0x00000402, 0x3dc6547e },
194 0x00000bdd, 0x00000bdd, 0x06519578,
195 0x3ff007da, 0x00000be3, 0x03c24973,
196 0x3ff003d9, 0x00000be9, 0x01b30d5f,
197 0x3ffff7df, 0x001003f1, 0x0003c542,
198 0x000fdfec, 0x001003f7, 0x3ec4711d,
199 0x000fc400, 0x002ffffd, 0x3df504f1,
200 0x001fa81a, 0x002ffc00, 0x3d957cc2,
201 0x002f8c3c, 0x00100000, 0x3db5c891 },
204 0x3ff003dc, 0x3ff003dc, 0x0791e558,
205 0x000ff7dd, 0x3ff007de, 0x05328554,
206 0x000fe7e3, 0x3ff00be2, 0x03232546,
207 0x000fd7ee, 0x000007e9, 0x0143bd30,
208 0x001fb800, 0x000007ee, 0x00044511,
209 0x002fa015, 0x000007f4, 0x3ef4bcee,
210 0x002f8832, 0x001003f9, 0x3e4514c7,
211 0x001f7853, 0x001003fd, 0x3de54c9f },
214 0x000fefe0, 0x000fefe0, 0x08721d3c,
215 0x001fdbe7, 0x000ffbde, 0x0652a139,
216 0x001fcbf0, 0x000003df, 0x0463292e,
217 0x002fb3ff, 0x3ff007e3, 0x0293a91d,
218 0x002f9c12, 0x3ff00be7, 0x01241905,
219 0x001f8c29, 0x000007ed, 0x3fe470eb,
220 0x000f7c46, 0x000007f2, 0x3f04b8ca,
221 0x3fef7865, 0x000007f6, 0x3e74e4a8 },
224 0x001fd3e9, 0x001fd3e9, 0x08f23d26,
225 0x002fbff3, 0x001fe3e4, 0x0712ad23,
226 0x002fa800, 0x000ff3e0, 0x05631d1b,
227 0x001f9810, 0x000ffbe1, 0x03b3890d,
228 0x000f8c23, 0x000003e3, 0x0233e8fa,
229 0x3fef843b, 0x000003e7, 0x00f430e4,
230 0x3fbf8456, 0x3ff00bea, 0x00046cc8,
231 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
234 0x001fbbf4, 0x001fbbf4, 0x09425112,
235 0x001fa800, 0x002fc7ed, 0x0792b110,
236 0x000f980e, 0x001fdbe6, 0x0613110a,
237 0x3fff8c20, 0x001fe7e3, 0x04a368fd,
238 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
239 0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
240 0x3f5f9c61, 0x000003e6, 0x00e428c5,
241 0x3f1fb07b, 0x000003eb, 0x3fe440af },
244 0x000fa400, 0x000fa400, 0x09625902,
245 0x3fff980c, 0x001fb7f5, 0x0812b0ff,
246 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
247 0x3faf902d, 0x001fd3e8, 0x055348f1,
248 0x3f7f983f, 0x001fe3e5, 0x04038ce3,
249 0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
250 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
251 0x3ecfd880, 0x000fffe6, 0x00c404ac },
254 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
255 0x3fbf9818, 0x3fffa400, 0x0842a8f1,
256 0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
257 0x3f5fa037, 0x000fc3ef, 0x05d330e4,
258 0x3f2fac49, 0x001fcfea, 0x04a364d9,
259 0x3effc05c, 0x001fdbe7, 0x038394ca,
260 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
261 0x3ea00083, 0x001fefe6, 0x0183c0a9 },
264 0x3f9fa014, 0x3f9fa014, 0x098260e6,
265 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
266 0x3f4fa431, 0x3fefa400, 0x0742d8e1,
267 0x3f1fb440, 0x3fffb3f8, 0x062310d9,
268 0x3eefc850, 0x000fbbf2, 0x050340d0,
269 0x3ecfe062, 0x000fcbec, 0x041364c2,
270 0x3ea00073, 0x001fd3ea, 0x03037cb5,
271 0x3e902086, 0x001fdfe8, 0x022388a5 },
274 0x3f5fa81e, 0x3f5fa81e, 0x096258da,
275 0x3f3fac2b, 0x3f8fa412, 0x088290d8,
276 0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
277 0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
278 0x3ecfe456, 0x3fefaffa, 0x05531cc6,
279 0x3eb00066, 0x3fffbbf3, 0x047334bb,
280 0x3ea01c77, 0x000fc7ee, 0x039348ae,
281 0x3ea04486, 0x000fd3eb, 0x02b350a1 },
284 0x3f2fb426, 0x3f2fb426, 0x094250ce,
285 0x3f0fc032, 0x3f4fac1b, 0x086284cd,
286 0x3eefd040, 0x3f7fa811, 0x0782acc9,
287 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
288 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
289 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
290 0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
291 0x3ec06884, 0x000fbff2, 0x03031c9e },
294 0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
295 0x3eefd439, 0x3f2fb822, 0x08526cc2,
296 0x3edfe845, 0x3f4fb018, 0x078294bf,
297 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
298 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
299 0x3ec0386b, 0x3fafac00, 0x0502e8ac,
300 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
301 0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
304 0x3eefdc31, 0x3eefdc31, 0x08e238b8,
305 0x3edfec3d, 0x3f0fc828, 0x082258b9,
306 0x3ed00049, 0x3f1fc01e, 0x077278b6,
307 0x3ed01455, 0x3f3fb815, 0x06c294b2,
308 0x3ed03460, 0x3f5fb40d, 0x0602acac,
309 0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
310 0x3f107476, 0x3f9fb400, 0x0472c89d,
311 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
314 0x3eefec37, 0x3eefec37, 0x088220b0,
315 0x3ee00041, 0x3effdc2d, 0x07f244ae,
316 0x3ee0144c, 0x3f0fd023, 0x07625cad,
317 0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
318 0x3f004861, 0x3f3fbc13, 0x060288a6,
319 0x3f20686b, 0x3f5fb80c, 0x05529c9e,
320 0x3f408c74, 0x3f6fb805, 0x04b2ac96,
321 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
324 0x3ef0003a, 0x3ef0003a, 0x084210a6,
325 0x3ef01045, 0x3effec32, 0x07b228a7,
326 0x3f00284e, 0x3f0fdc29, 0x073244a4,
327 0x3f104058, 0x3f0fd420, 0x06a258a2,
328 0x3f305c62, 0x3f2fc818, 0x0612689d,
329 0x3f508069, 0x3f3fc011, 0x05728496,
330 0x3f80a072, 0x3f4fc00a, 0x04d28c90,
331 0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
334 0x3f00103e, 0x3f00103e, 0x07f1fc9e,
335 0x3f102447, 0x3f000035, 0x0782149d,
336 0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
337 0x3f405458, 0x3f0fe424, 0x06924099,
338 0x3f607061, 0x3f1fd41d, 0x06024c97,
339 0x3f909068, 0x3f2fcc16, 0x05726490,
340 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
341 0x0000d077, 0x3f4fc409, 0x04627484 },
344 0x3f202040, 0x3f202040, 0x07a1e898,
345 0x3f303449, 0x3f100c38, 0x0741fc98,
346 0x3f504c50, 0x3f10002f, 0x06e21495,
347 0x3f706459, 0x3f1ff028, 0x06722492,
348 0x3fa08060, 0x3f1fe421, 0x05f2348f,
349 0x3fd09c67, 0x3f1fdc19, 0x05824c89,
350 0x0000bc6e, 0x3f2fd014, 0x04f25086,
351 0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
354 0x3f403042, 0x3f403042, 0x0761d890,
355 0x3f504848, 0x3f301c3b, 0x0701f090,
356 0x3f805c50, 0x3f200c33, 0x06a2008f,
357 0x3fa07458, 0x3f10002b, 0x06520c8d,
358 0x3fd0905e, 0x3f1ff424, 0x05e22089,
359 0x0000ac65, 0x3f1fe81d, 0x05823483,
360 0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
361 0x0080e871, 0x3f2fd412, 0x0482407c },
364 0x3f604043, 0x3f604043, 0x0721c88a,
365 0x3f80544a, 0x3f502c3c, 0x06d1d88a,
366 0x3fb06851, 0x3f301c35, 0x0681e889,
367 0x3fd08456, 0x3f30082f, 0x0611fc88,
368 0x00009c5d, 0x3f200027, 0x05d20884,
369 0x0030b863, 0x3f2ff421, 0x05621880,
370 0x0070d468, 0x3f2fe81b, 0x0502247c,
371 0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
374 0x3f904c44, 0x3f904c44, 0x06e1b884,
375 0x3fb0604a, 0x3f70383e, 0x0691c885,
376 0x3fe07451, 0x3f502c36, 0x0661d483,
377 0x00009055, 0x3f401831, 0x0601ec81,
378 0x0030a85b, 0x3f300c2a, 0x05b1f480,
379 0x0070c061, 0x3f300024, 0x0562047a,
380 0x00b0d867, 0x3f3ff41e, 0x05020c77,
381 0x00f0f46b, 0x3f2fec19, 0x04a21474 },
384 0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
385 0x3fe06c4b, 0x3f902c3f, 0x0681c081,
386 0x0000844f, 0x3f703838, 0x0631cc7d,
387 0x00309855, 0x3f602433, 0x05d1d47e,
388 0x0060b459, 0x3f50142e, 0x0581e47b,
389 0x00a0c85f, 0x3f400828, 0x0531f078,
390 0x00e0e064, 0x3f300021, 0x0501fc73,
391 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
394 0x3fe06444, 0x3fe06444, 0x0681a07a,
395 0x00007849, 0x3fc0503f, 0x0641b07a,
396 0x0020904d, 0x3fa0403a, 0x05f1c07a,
397 0x0060a453, 0x3f803034, 0x05c1c878,
398 0x0090b858, 0x3f70202f, 0x0571d477,
399 0x00d0d05d, 0x3f501829, 0x0531e073,
400 0x0110e462, 0x3f500825, 0x04e1e471,
401 0x01510065, 0x3f40001f, 0x04a1f06d },
404 0x00007044, 0x00007044, 0x06519476,
405 0x00208448, 0x3fe05c3f, 0x0621a476,
406 0x0050984d, 0x3fc04c3a, 0x05e1b075,
407 0x0080ac52, 0x3fa03c35, 0x05a1b875,
408 0x00c0c056, 0x3f803030, 0x0561c473,
409 0x0100d45b, 0x3f70202b, 0x0521d46f,
410 0x0140e860, 0x3f601427, 0x04d1d46e,
411 0x01810064, 0x3f500822, 0x0491dc6b },
414 0x0110a442, 0x0110a442, 0x0551545e,
415 0x0140b045, 0x00e0983f, 0x0531585f,
416 0x0160c047, 0x00c08c3c, 0x0511645e,
417 0x0190cc4a, 0x00908039, 0x04f1685f,
418 0x01c0dc4c, 0x00707436, 0x04d1705e,
419 0x0200e850, 0x00506833, 0x04b1785b,
420 0x0230f453, 0x00305c30, 0x0491805a,
421 0x02710056, 0x0010542d, 0x04718059 },
424 0x01c0bc40, 0x01c0bc40, 0x04c13052,
425 0x01e0c841, 0x01a0b43d, 0x04c13851,
426 0x0210cc44, 0x0180a83c, 0x04a13453,
427 0x0230d845, 0x0160a03a, 0x04913c52,
428 0x0260e047, 0x01409838, 0x04714052,
429 0x0280ec49, 0x01208c37, 0x04514c50,
430 0x02b0f44b, 0x01008435, 0x04414c50,
431 0x02d1004c, 0x00e07c33, 0x0431544f },
434 0x0230c83e, 0x0230c83e, 0x04711c4c,
435 0x0250d03f, 0x0210c43c, 0x0471204b,
436 0x0270d840, 0x0200b83c, 0x0451244b,
437 0x0290dc42, 0x01e0b43a, 0x0441244c,
438 0x02b0e443, 0x01c0b038, 0x0441284b,
439 0x02d0ec44, 0x01b0a438, 0x0421304a,
440 0x02f0f445, 0x0190a036, 0x04213449,
441 0x0310f847, 0x01709c34, 0x04213848 },
444 0x0280d03d, 0x0280d03d, 0x04310c48,
445 0x02a0d43e, 0x0270c83c, 0x04311047,
446 0x02b0dc3e, 0x0250c83a, 0x04311447,
447 0x02d0e040, 0x0240c03a, 0x04211446,
448 0x02e0e840, 0x0220bc39, 0x04111847,
449 0x0300e842, 0x0210b438, 0x04012445,
450 0x0310f043, 0x0200b037, 0x04012045,
451 0x0330f444, 0x01e0ac36, 0x03f12445 },
454 0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
455 0x0340e03a, 0x0330e039, 0x03c0f03e,
456 0x0350e03b, 0x0330dc39, 0x03c0ec3e,
457 0x0350e43a, 0x0320dc38, 0x03c0f43e,
458 0x0360e43b, 0x0320d839, 0x03b0f03e,
459 0x0360e83b, 0x0310d838, 0x03c0fc3b,
460 0x0370e83b, 0x0310d439, 0x03a0f83d,
461 0x0370e83c, 0x0300d438, 0x03b0fc3c },
465 enum rcar_vin_state {
471 struct rcar_vin_priv {
475 /* State of the VIN module in capturing mode */
476 enum rcar_vin_state state;
477 struct soc_camera_host ici;
478 struct list_head capture;
479 #define MAX_BUFFER_NUM 3
480 struct vb2_buffer *queue_buf[MAX_BUFFER_NUM];
481 struct vb2_alloc_ctx *alloc_ctx;
482 enum v4l2_field field;
483 unsigned int pdata_flags;
484 unsigned int vb_count;
485 unsigned int nr_hw_slots;
486 bool request_to_stop;
487 struct completion capture_stop;
491 #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
493 struct rcar_vin_buffer {
494 struct vb2_buffer vb;
495 struct list_head list;
498 #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
499 struct rcar_vin_buffer, \
502 struct rcar_vin_cam {
503 /* VIN offsets within the camera output, before the VIN scaler */
504 unsigned int vin_left;
505 unsigned int vin_top;
506 /* Client output, as seen by the VIN */
509 /* User window from S_FMT */
510 unsigned int out_width;
511 unsigned int out_height;
513 * User window from S_CROP / G_CROP, produced by client cropping and
514 * scaling, VIN scaling and VIN cropping, mapped back onto the client
517 struct v4l2_rect subrect;
518 /* Camera cropping rectangle */
519 struct v4l2_rect rect;
520 const struct soc_mbus_pixelfmt *extra_fmt;
524 * .queue_setup() is called to check whether the driver can accept the requested
525 * number of buffers and to fill in plane sizes for the current frame format if
528 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
529 const struct v4l2_format *fmt,
531 unsigned int *num_planes,
532 unsigned int sizes[], void *alloc_ctxs[])
534 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
535 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
536 struct rcar_vin_priv *priv = ici->priv;
539 const struct soc_camera_format_xlate *xlate;
540 unsigned int bytes_per_line;
543 xlate = soc_camera_xlate_by_fourcc(icd,
544 fmt->fmt.pix.pixelformat);
547 ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
552 bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret);
554 ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line,
555 fmt->fmt.pix.height);
559 sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret);
561 /* Called from VIDIOC_REQBUFS or in compatibility mode */
562 sizes[0] = icd->sizeimage;
565 alloc_ctxs[0] = priv->alloc_ctx;
567 if (!vq->num_buffers)
572 priv->vb_count = *count;
576 /* Number of hardware slots */
577 if (is_continuous_transfer(priv))
578 priv->nr_hw_slots = MAX_BUFFER_NUM;
580 priv->nr_hw_slots = 1;
582 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
587 static int rcar_vin_setup(struct rcar_vin_priv *priv)
589 struct soc_camera_device *icd = priv->ici.icd;
590 struct rcar_vin_cam *cam = icd->host_priv;
591 u32 vnmc, dmr, interrupts;
592 bool progressive = false, output_is_yuv = false;
594 switch (priv->field) {
598 case V4L2_FIELD_BOTTOM:
601 case V4L2_FIELD_INTERLACED:
602 case V4L2_FIELD_INTERLACED_TB:
605 case V4L2_FIELD_INTERLACED_BT:
606 vnmc = VNMC_IM_FULL | VNMC_FOC;
608 case V4L2_FIELD_NONE:
609 if (is_continuous_transfer(priv)) {
610 vnmc = VNMC_IM_ODD_EVEN;
621 /* input interface */
622 switch (icd->current_fmt->code) {
623 case MEDIA_BUS_FMT_YUYV8_1X16:
624 /* BT.601/BT.1358 16bit YCbCr422 */
625 vnmc |= VNMC_INF_YUV16;
627 case MEDIA_BUS_FMT_YUYV8_2X8:
628 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
629 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
630 VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
632 case MEDIA_BUS_FMT_YUYV10_2X10:
633 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
634 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
635 VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
642 switch (icd->current_fmt->host_fmt->fourcc) {
643 case V4L2_PIX_FMT_NV16:
644 iowrite32(ALIGN(cam->width * cam->height, 0x80),
645 priv->base + VNUVAOF_REG);
646 dmr = VNDMR_DTMD_YCSEP;
647 output_is_yuv = true;
649 case V4L2_PIX_FMT_YUYV:
651 output_is_yuv = true;
653 case V4L2_PIX_FMT_UYVY:
655 output_is_yuv = true;
657 case V4L2_PIX_FMT_RGB555X:
658 dmr = VNDMR_DTMD_ARGB1555;
660 case V4L2_PIX_FMT_RGB565:
663 case V4L2_PIX_FMT_RGB32:
664 if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 ||
665 priv->chip == RCAR_E1) {
670 dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
671 icd->current_fmt->host_fmt->fourcc);
675 /* Always update on field change */
678 /* If input and output use the same colorspace, use bypass mode */
682 /* progressive or interlaced mode */
683 interrupts = progressive ? VNIE_FIE : VNIE_EFE;
686 iowrite32(interrupts, priv->base + VNINTS_REG);
687 /* enable interrupts */
688 iowrite32(interrupts, priv->base + VNIE_REG);
689 /* start capturing */
690 iowrite32(dmr, priv->base + VNDMR_REG);
691 iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
696 static void rcar_vin_capture(struct rcar_vin_priv *priv)
698 if (is_continuous_transfer(priv))
699 /* Continuous Frame Capture Mode */
700 iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
702 /* Single Frame Capture Mode */
703 iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
706 static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
708 priv->state = STOPPING;
710 /* set continuous & single transfer off */
711 iowrite32(0, priv->base + VNFC_REG);
712 /* disable capture (release DMA buffer), reset */
713 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
714 priv->base + VNMC_REG);
716 /* update the status if stopped already */
717 if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
718 priv->state = STOPPED;
721 static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
725 for (slot = 0; slot < priv->nr_hw_slots; slot++)
726 if (priv->queue_buf[slot] == NULL)
732 static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
734 /* Ensure all HW slots are filled */
735 return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
738 /* Moves a buffer from the queue to the HW slots */
739 static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
741 struct vb2_buffer *vb;
742 dma_addr_t phys_addr_top;
745 if (list_empty(&priv->capture))
748 /* Find a free HW slot */
749 slot = rcar_vin_get_free_hw_slot(priv);
753 vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb;
754 list_del_init(to_buf_list(vb));
755 priv->queue_buf[slot] = vb;
756 phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0);
757 iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
762 static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
764 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
765 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
766 struct rcar_vin_priv *priv = ici->priv;
769 size = icd->sizeimage;
771 if (vb2_plane_size(vb, 0) < size) {
772 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
773 vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
777 vb2_set_plane_payload(vb, 0, size);
779 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
780 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
782 spin_lock_irq(&priv->lock);
784 list_add_tail(to_buf_list(vb), &priv->capture);
785 rcar_vin_fill_hw_slot(priv);
787 /* If we weren't running, and have enough buffers, start capturing! */
788 if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
789 if (rcar_vin_setup(priv)) {
791 list_del_init(to_buf_list(vb));
792 spin_unlock_irq(&priv->lock);
795 priv->request_to_stop = false;
796 init_completion(&priv->capture_stop);
797 priv->state = RUNNING;
798 rcar_vin_capture(priv);
801 spin_unlock_irq(&priv->lock);
806 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
810 * Wait for capture to stop and all in-flight buffers to be finished with by
811 * the video hardware. This must be called under &priv->lock
814 static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
816 while (priv->state != STOPPED) {
817 /* issue stop if running */
818 if (priv->state == RUNNING)
819 rcar_vin_request_capture_stop(priv);
821 /* wait until capturing has been stopped */
822 if (priv->state == STOPPING) {
823 priv->request_to_stop = true;
824 spin_unlock_irq(&priv->lock);
825 if (!wait_for_completion_timeout(
827 msecs_to_jiffies(TIMEOUT_MS)))
828 priv->state = STOPPED;
829 spin_lock_irq(&priv->lock);
834 static void rcar_vin_stop_streaming(struct vb2_queue *vq)
836 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
837 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
838 struct rcar_vin_priv *priv = ici->priv;
839 struct list_head *buf_head, *tmp;
842 spin_lock_irq(&priv->lock);
843 rcar_vin_wait_stop_streaming(priv);
845 for (i = 0; i < MAX_BUFFER_NUM; i++) {
846 if (priv->queue_buf[i]) {
847 vb2_buffer_done(priv->queue_buf[i],
848 VB2_BUF_STATE_ERROR);
849 priv->queue_buf[i] = NULL;
853 list_for_each_safe(buf_head, tmp, &priv->capture) {
854 vb2_buffer_done(&list_entry(buf_head,
855 struct rcar_vin_buffer, list)->vb,
856 VB2_BUF_STATE_ERROR);
857 list_del_init(buf_head);
859 spin_unlock_irq(&priv->lock);
862 static struct vb2_ops rcar_vin_vb2_ops = {
863 .queue_setup = rcar_vin_videobuf_setup,
864 .buf_queue = rcar_vin_videobuf_queue,
865 .stop_streaming = rcar_vin_stop_streaming,
866 .wait_prepare = vb2_ops_wait_prepare,
867 .wait_finish = vb2_ops_wait_finish,
870 static irqreturn_t rcar_vin_irq(int irq, void *data)
872 struct rcar_vin_priv *priv = data;
874 bool can_run = false, hw_stopped;
876 unsigned int handled = 0;
878 spin_lock(&priv->lock);
880 int_status = ioread32(priv->base + VNINTS_REG);
884 iowrite32(int_status, priv->base + VNINTS_REG);
887 /* nothing to do if capture status is 'STOPPED' */
888 if (priv->state == STOPPED)
891 hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
893 if (!priv->request_to_stop) {
894 if (is_continuous_transfer(priv))
895 slot = (ioread32(priv->base + VNMS_REG) &
896 VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
900 priv->queue_buf[slot]->v4l2_buf.field = priv->field;
901 priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++;
902 do_gettimeofday(&priv->queue_buf[slot]->v4l2_buf.timestamp);
903 vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE);
904 priv->queue_buf[slot] = NULL;
906 if (priv->state != STOPPING)
907 can_run = rcar_vin_fill_hw_slot(priv);
909 if (hw_stopped || !can_run) {
910 priv->state = STOPPED;
911 } else if (is_continuous_transfer(priv) &&
912 list_empty(&priv->capture) &&
913 priv->state == RUNNING) {
915 * The continuous capturing requires an explicit stop
916 * operation when there is no buffer to be set into
917 * the VnMBm registers.
919 rcar_vin_request_capture_stop(priv);
921 rcar_vin_capture(priv);
924 } else if (hw_stopped) {
925 priv->state = STOPPED;
926 priv->request_to_stop = false;
927 complete(&priv->capture_stop);
931 spin_unlock(&priv->lock);
933 return IRQ_RETVAL(handled);
936 static int rcar_vin_add_device(struct soc_camera_device *icd)
938 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
939 struct rcar_vin_priv *priv = ici->priv;
942 for (i = 0; i < MAX_BUFFER_NUM; i++)
943 priv->queue_buf[i] = NULL;
945 pm_runtime_get_sync(ici->v4l2_dev.dev);
947 dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
953 static void rcar_vin_remove_device(struct soc_camera_device *icd)
955 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
956 struct rcar_vin_priv *priv = ici->priv;
957 struct vb2_buffer *vb;
960 /* disable capture, disable interrupts */
961 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
962 priv->base + VNMC_REG);
963 iowrite32(0, priv->base + VNIE_REG);
965 priv->state = STOPPED;
966 priv->request_to_stop = false;
968 /* make sure active buffer is cancelled */
969 spin_lock_irq(&priv->lock);
970 for (i = 0; i < MAX_BUFFER_NUM; i++) {
971 vb = priv->queue_buf[i];
973 list_del_init(to_buf_list(vb));
974 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
977 spin_unlock_irq(&priv->lock);
979 pm_runtime_put(ici->v4l2_dev.dev);
981 dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
985 static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
988 const struct vin_coeff *p_prev_set = NULL;
989 const struct vin_coeff *p_set = NULL;
991 /* Look for suitable coefficient values */
992 for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
994 p_set = &vin_coeff_set[i];
996 if (xs < p_set->xs_value)
1000 /* Use previous value if its XS value is closer */
1001 if (p_prev_set && p_set &&
1002 xs - p_prev_set->xs_value < p_set->xs_value - xs)
1005 /* Set coefficient registers */
1006 iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
1007 iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
1008 iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
1010 iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
1011 iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
1012 iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
1014 iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
1015 iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
1016 iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
1018 iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
1019 iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
1020 iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
1022 iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
1023 iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
1024 iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
1026 iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
1027 iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
1028 iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
1030 iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
1031 iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
1032 iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
1034 iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
1035 iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
1036 iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
1039 /* rect is guaranteed to not exceed the scaled camera rectangle */
1040 static int rcar_vin_set_rect(struct soc_camera_device *icd)
1042 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1043 struct rcar_vin_cam *cam = icd->host_priv;
1044 struct rcar_vin_priv *priv = ici->priv;
1045 unsigned int left_offset, top_offset;
1046 unsigned char dsize = 0;
1047 struct v4l2_rect *cam_subrect = &cam->subrect;
1050 dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
1051 icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
1053 left_offset = cam->vin_left;
1054 top_offset = cam->vin_top;
1056 if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 &&
1057 priv->chip == RCAR_E1)
1060 dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
1061 cam->width, cam->height, cam->vin_left, cam->vin_top);
1062 dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
1063 cam_subrect->width, cam_subrect->height,
1064 cam_subrect->left, cam_subrect->top);
1066 /* Set Start/End Pixel/Line Pre-Clip */
1067 iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
1068 iowrite32((left_offset + cam_subrect->width - 1) << dsize,
1069 priv->base + VNEPPRC_REG);
1070 switch (priv->field) {
1071 case V4L2_FIELD_INTERLACED:
1072 case V4L2_FIELD_INTERLACED_TB:
1073 case V4L2_FIELD_INTERLACED_BT:
1074 iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
1075 iowrite32((top_offset + cam_subrect->height) / 2 - 1,
1076 priv->base + VNELPRC_REG);
1079 iowrite32(top_offset, priv->base + VNSLPRC_REG);
1080 iowrite32(top_offset + cam_subrect->height - 1,
1081 priv->base + VNELPRC_REG);
1085 /* Set scaling coefficient */
1087 if (cam_subrect->height != cam->out_height)
1088 value = (4096 * cam_subrect->height) / cam->out_height;
1089 dev_dbg(icd->parent, "YS Value: %x\n", value);
1090 iowrite32(value, priv->base + VNYS_REG);
1093 if (cam_subrect->width != cam->out_width)
1094 value = (4096 * cam_subrect->width) / cam->out_width;
1096 /* Horizontal upscaling is up to double size */
1097 if (0 < value && value < 2048)
1100 dev_dbg(icd->parent, "XS Value: %x\n", value);
1101 iowrite32(value, priv->base + VNXS_REG);
1103 /* Horizontal upscaling is carried out by scaling down from double size */
1107 set_coeff(priv, value);
1109 /* Set Start/End Pixel/Line Post-Clip */
1110 iowrite32(0, priv->base + VNSPPOC_REG);
1111 iowrite32(0, priv->base + VNSLPOC_REG);
1112 iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
1113 switch (priv->field) {
1114 case V4L2_FIELD_INTERLACED:
1115 case V4L2_FIELD_INTERLACED_TB:
1116 case V4L2_FIELD_INTERLACED_BT:
1117 iowrite32(cam->out_height / 2 - 1,
1118 priv->base + VNELPOC_REG);
1121 iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
1125 iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
1130 static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
1132 *vnmc = ioread32(priv->base + VNMC_REG);
1133 /* module disable */
1134 iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
1137 static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
1139 unsigned long timeout = jiffies + 10 * HZ;
1142 * Wait until the end of the current frame. It can take a long time,
1143 * but if it has been aborted by a MRST1 reset, it should exit sooner.
1145 while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
1146 time_before(jiffies, timeout))
1149 if (time_after(jiffies, timeout)) {
1150 dev_err(priv->ici.v4l2_dev.dev,
1151 "Timeout waiting for frame end! Interface problem?\n");
1155 iowrite32(vnmc, priv->base + VNMC_REG);
1158 #define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \
1159 V4L2_MBUS_PCLK_SAMPLE_RISING | \
1160 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
1161 V4L2_MBUS_HSYNC_ACTIVE_LOW | \
1162 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
1163 V4L2_MBUS_VSYNC_ACTIVE_LOW | \
1164 V4L2_MBUS_DATA_ACTIVE_HIGH)
1166 static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
1168 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1169 struct rcar_vin_priv *priv = ici->priv;
1170 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1171 struct v4l2_mbus_config cfg;
1172 unsigned long common_flags;
1177 capture_stop_preserve(priv, &vnmc);
1179 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1181 common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1182 if (!common_flags) {
1183 dev_warn(icd->parent,
1184 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1185 cfg.flags, VIN_MBUS_FLAGS);
1188 } else if (ret != -ENOIOCTLCMD) {
1191 common_flags = VIN_MBUS_FLAGS;
1194 /* Make choises, based on platform preferences */
1195 if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1196 (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
1197 if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
1198 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1200 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1203 if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1204 (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
1205 if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
1206 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1208 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1211 cfg.flags = common_flags;
1212 ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1213 if (ret < 0 && ret != -ENOIOCTLCMD)
1216 val = VNDMR2_FTEV | VNDMR2_VLV(1);
1217 if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
1219 if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
1221 iowrite32(val, priv->base + VNDMR2_REG);
1223 ret = rcar_vin_set_rect(icd);
1227 capture_restore(priv, vnmc);
1232 static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
1233 unsigned char buswidth)
1235 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1236 struct v4l2_mbus_config cfg;
1239 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1240 if (ret == -ENOIOCTLCMD)
1248 /* check is there common mbus flags */
1249 ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1253 dev_warn(icd->parent,
1254 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1255 cfg.flags, VIN_MBUS_FLAGS);
1260 static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1262 return fmt->packing == SOC_MBUS_PACKING_NONE ||
1263 (fmt->bits_per_sample > 8 &&
1264 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1267 static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
1269 .fourcc = V4L2_PIX_FMT_NV16,
1271 .bits_per_sample = 8,
1272 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1273 .order = SOC_MBUS_ORDER_LE,
1274 .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
1277 .fourcc = V4L2_PIX_FMT_YUYV,
1279 .bits_per_sample = 16,
1280 .packing = SOC_MBUS_PACKING_NONE,
1281 .order = SOC_MBUS_ORDER_LE,
1282 .layout = SOC_MBUS_LAYOUT_PACKED,
1285 .fourcc = V4L2_PIX_FMT_UYVY,
1287 .bits_per_sample = 16,
1288 .packing = SOC_MBUS_PACKING_NONE,
1289 .order = SOC_MBUS_ORDER_LE,
1290 .layout = SOC_MBUS_LAYOUT_PACKED,
1293 .fourcc = V4L2_PIX_FMT_RGB565,
1295 .bits_per_sample = 16,
1296 .packing = SOC_MBUS_PACKING_NONE,
1297 .order = SOC_MBUS_ORDER_LE,
1298 .layout = SOC_MBUS_LAYOUT_PACKED,
1301 .fourcc = V4L2_PIX_FMT_RGB555X,
1303 .bits_per_sample = 16,
1304 .packing = SOC_MBUS_PACKING_NONE,
1305 .order = SOC_MBUS_ORDER_LE,
1306 .layout = SOC_MBUS_LAYOUT_PACKED,
1309 .fourcc = V4L2_PIX_FMT_RGB32,
1311 .bits_per_sample = 32,
1312 .packing = SOC_MBUS_PACKING_NONE,
1313 .order = SOC_MBUS_ORDER_LE,
1314 .layout = SOC_MBUS_LAYOUT_PACKED,
1318 static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
1319 struct soc_camera_format_xlate *xlate)
1321 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1322 struct device *dev = icd->parent;
1325 struct rcar_vin_cam *cam;
1327 const struct soc_mbus_pixelfmt *fmt;
1329 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1333 fmt = soc_mbus_get_fmtdesc(code);
1335 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code);
1339 ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1343 if (!icd->host_priv) {
1344 struct v4l2_mbus_framefmt mf;
1345 struct v4l2_rect rect;
1346 struct device *dev = icd->parent;
1349 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1353 /* Cache current client geometry */
1354 ret = soc_camera_client_g_rect(sd, &rect);
1355 if (ret == -ENOIOCTLCMD) {
1356 /* Sensor driver doesn't support cropping */
1359 rect.width = mf.width;
1360 rect.height = mf.height;
1361 } else if (ret < 0) {
1366 * If sensor proposes too large format then try smaller ones:
1367 * 1280x960, 640x480, 320x240
1369 for (shift = 0; shift < 3; shift++) {
1370 if (mf.width <= VIN_MAX_WIDTH &&
1371 mf.height <= VIN_MAX_HEIGHT)
1374 mf.width = 1280 >> shift;
1375 mf.height = 960 >> shift;
1376 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1377 soc_camera_grp_id(icd),
1386 "Failed to configure the client below %ux%u\n",
1387 mf.width, mf.height);
1391 dev_dbg(dev, "camera fmt %ux%u\n", mf.width, mf.height);
1393 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1397 * We are called with current camera crop,
1398 * initialise subrect with it
1401 cam->subrect = rect;
1402 cam->width = mf.width;
1403 cam->height = mf.height;
1404 cam->out_width = mf.width;
1405 cam->out_height = mf.height;
1407 icd->host_priv = cam;
1409 cam = icd->host_priv;
1412 /* Beginning of a pass */
1414 cam->extra_fmt = NULL;
1417 case MEDIA_BUS_FMT_YUYV8_1X16:
1418 case MEDIA_BUS_FMT_YUYV8_2X8:
1419 case MEDIA_BUS_FMT_YUYV10_2X10:
1423 /* Add all our formats that can be generated by VIN */
1424 cam->extra_fmt = rcar_vin_formats;
1426 n = ARRAY_SIZE(rcar_vin_formats);
1428 for (k = 0; xlate && k < n; k++, xlate++) {
1429 xlate->host_fmt = &rcar_vin_formats[k];
1431 dev_dbg(dev, "Providing format %s using code %d\n",
1432 rcar_vin_formats[k].name, code);
1436 if (!rcar_vin_packing_supported(fmt))
1439 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1444 /* Generic pass-through */
1447 xlate->host_fmt = fmt;
1455 static void rcar_vin_put_formats(struct soc_camera_device *icd)
1457 kfree(icd->host_priv);
1458 icd->host_priv = NULL;
1461 static int rcar_vin_set_crop(struct soc_camera_device *icd,
1462 const struct v4l2_crop *a)
1464 struct v4l2_crop a_writable = *a;
1465 const struct v4l2_rect *rect = &a_writable.c;
1466 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1467 struct rcar_vin_priv *priv = ici->priv;
1468 struct v4l2_crop cam_crop;
1469 struct rcar_vin_cam *cam = icd->host_priv;
1470 struct v4l2_rect *cam_rect = &cam_crop.c;
1471 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1472 struct device *dev = icd->parent;
1473 struct v4l2_mbus_framefmt mf;
1477 dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
1478 rect->left, rect->top);
1480 /* During camera cropping its output window can change too, stop VIN */
1481 capture_stop_preserve(priv, &vnmc);
1482 dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1484 /* Apply iterative camera S_CROP for new input window. */
1485 ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
1486 &cam->rect, &cam->subrect);
1490 dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
1491 cam_rect->width, cam_rect->height,
1492 cam_rect->left, cam_rect->top);
1494 /* On success cam_crop contains current camera crop */
1496 /* Retrieve camera output window */
1497 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1501 if (mf.width > VIN_MAX_WIDTH || mf.height > VIN_MAX_HEIGHT)
1504 /* Cache camera output window */
1505 cam->width = mf.width;
1506 cam->height = mf.height;
1508 icd->user_width = cam->width;
1509 icd->user_height = cam->height;
1511 cam->vin_left = rect->left & ~1;
1512 cam->vin_top = rect->top & ~1;
1514 /* Use VIN cropping to crop to the new window. */
1515 ret = rcar_vin_set_rect(icd);
1519 cam->subrect = *rect;
1521 dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
1522 icd->user_width, icd->user_height,
1523 cam->vin_left, cam->vin_top);
1525 /* Restore capture */
1526 for (i = 0; i < MAX_BUFFER_NUM; i++) {
1527 if (priv->queue_buf[i] && priv->state == STOPPED) {
1532 capture_restore(priv, vnmc);
1534 /* Even if only camera cropping succeeded */
1538 static int rcar_vin_get_crop(struct soc_camera_device *icd,
1539 struct v4l2_crop *a)
1541 struct rcar_vin_cam *cam = icd->host_priv;
1543 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1544 a->c = cam->subrect;
1549 /* Similar to set_crop multistage iterative algorithm */
1550 static int rcar_vin_set_fmt(struct soc_camera_device *icd,
1551 struct v4l2_format *f)
1553 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1554 struct rcar_vin_priv *priv = ici->priv;
1555 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1556 struct rcar_vin_cam *cam = icd->host_priv;
1557 struct v4l2_pix_format *pix = &f->fmt.pix;
1558 struct v4l2_mbus_framefmt mf;
1559 struct device *dev = icd->parent;
1560 __u32 pixfmt = pix->pixelformat;
1561 const struct soc_camera_format_xlate *xlate;
1562 unsigned int vin_sub_width = 0, vin_sub_height = 0;
1565 enum v4l2_field field;
1568 dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
1569 pixfmt, pix->width, pix->height);
1571 switch (pix->field) {
1573 pix->field = V4L2_FIELD_NONE;
1575 case V4L2_FIELD_NONE:
1576 case V4L2_FIELD_TOP:
1577 case V4L2_FIELD_BOTTOM:
1578 case V4L2_FIELD_INTERLACED_TB:
1579 case V4L2_FIELD_INTERLACED_BT:
1582 case V4L2_FIELD_INTERLACED:
1583 /* Query for standard if not explicitly mentioned _TB/_BT */
1584 ret = v4l2_subdev_call(sd, video, querystd, &std);
1586 std = V4L2_STD_625_50;
1588 field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB :
1589 V4L2_FIELD_INTERLACED_BT;
1593 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1595 dev_warn(dev, "Format %x not found\n", pixfmt);
1598 /* Calculate client output geometry */
1599 soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1601 mf.field = pix->field;
1602 mf.colorspace = pix->colorspace;
1603 mf.code = xlate->code;
1606 case V4L2_PIX_FMT_RGB32:
1607 can_scale = priv->chip != RCAR_E1;
1609 case V4L2_PIX_FMT_UYVY:
1610 case V4L2_PIX_FMT_YUYV:
1611 case V4L2_PIX_FMT_RGB565:
1612 case V4L2_PIX_FMT_RGB555X:
1620 dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1622 ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1623 &mf, &vin_sub_width, &vin_sub_height,
1626 /* Done with the camera. Now see if we can improve the result */
1627 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1628 ret, mf.width, mf.height, pix->width, pix->height);
1630 if (ret == -ENOIOCTLCMD)
1631 dev_dbg(dev, "Sensor doesn't support scaling\n");
1635 if (mf.code != xlate->code)
1638 /* Prepare VIN crop */
1639 cam->width = mf.width;
1640 cam->height = mf.height;
1642 /* Use VIN scaling to scale to the requested user window. */
1644 /* We cannot scale up */
1645 if (pix->width > vin_sub_width)
1646 vin_sub_width = pix->width;
1648 if (pix->height > vin_sub_height)
1649 vin_sub_height = pix->height;
1651 pix->colorspace = mf.colorspace;
1654 pix->width = vin_sub_width;
1655 pix->height = vin_sub_height;
1659 * We have calculated CFLCR, the actual configuration will be performed
1660 * in rcar_vin_set_bus_param()
1663 dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1664 vin_sub_width, pix->width, vin_sub_height, pix->height);
1666 cam->out_width = pix->width;
1667 cam->out_height = pix->height;
1669 icd->current_fmt = xlate;
1671 priv->field = field;
1676 static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1677 struct v4l2_format *f)
1679 const struct soc_camera_format_xlate *xlate;
1680 struct v4l2_pix_format *pix = &f->fmt.pix;
1681 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1682 struct v4l2_mbus_framefmt mf;
1683 __u32 pixfmt = pix->pixelformat;
1687 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1689 xlate = icd->current_fmt;
1690 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1691 pixfmt, xlate->host_fmt->fourcc);
1692 pixfmt = xlate->host_fmt->fourcc;
1693 pix->pixelformat = pixfmt;
1694 pix->colorspace = icd->colorspace;
1697 /* FIXME: calculate using depth and bus width */
1698 v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1699 &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1702 height = pix->height;
1704 /* let soc-camera calculate these values */
1705 pix->bytesperline = 0;
1708 /* limit to sensor capabilities */
1709 mf.width = pix->width;
1710 mf.height = pix->height;
1711 mf.field = pix->field;
1712 mf.code = xlate->code;
1713 mf.colorspace = pix->colorspace;
1715 ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
1716 video, try_mbus_fmt, &mf);
1720 /* Adjust only if VIN cannot scale */
1721 if (pix->width > mf.width * 2)
1722 pix->width = mf.width * 2;
1723 if (pix->height > mf.height * 3)
1724 pix->height = mf.height * 3;
1726 pix->field = mf.field;
1727 pix->colorspace = mf.colorspace;
1729 if (pixfmt == V4L2_PIX_FMT_NV16) {
1730 /* FIXME: check against rect_max after converting soc-camera */
1731 /* We can scale precisely, need a bigger image from camera */
1732 if (pix->width < width || pix->height < height) {
1734 * We presume, the sensor behaves sanely, i.e. if
1735 * requested a bigger rectangle, it will not return a
1738 mf.width = VIN_MAX_WIDTH;
1739 mf.height = VIN_MAX_HEIGHT;
1740 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1741 soc_camera_grp_id(icd),
1742 video, try_mbus_fmt,
1745 dev_err(icd->parent,
1746 "client try_fmt() = %d\n", ret);
1750 /* We will scale exactly */
1751 if (mf.width > width)
1753 if (mf.height > height)
1754 pix->height = height;
1760 static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1762 struct soc_camera_device *icd = file->private_data;
1764 return vb2_poll(&icd->vb2_vidq, file, pt);
1767 static int rcar_vin_querycap(struct soc_camera_host *ici,
1768 struct v4l2_capability *cap)
1770 strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
1771 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1772 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1777 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1778 struct soc_camera_device *icd)
1780 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1782 vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1783 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1785 vq->ops = &rcar_vin_vb2_ops;
1786 vq->mem_ops = &vb2_dma_contig_memops;
1787 vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
1788 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1789 vq->lock = &ici->host_lock;
1791 return vb2_queue_init(vq);
1794 static struct soc_camera_host_ops rcar_vin_host_ops = {
1795 .owner = THIS_MODULE,
1796 .add = rcar_vin_add_device,
1797 .remove = rcar_vin_remove_device,
1798 .get_formats = rcar_vin_get_formats,
1799 .put_formats = rcar_vin_put_formats,
1800 .get_crop = rcar_vin_get_crop,
1801 .set_crop = rcar_vin_set_crop,
1802 .try_fmt = rcar_vin_try_fmt,
1803 .set_fmt = rcar_vin_set_fmt,
1804 .poll = rcar_vin_poll,
1805 .querycap = rcar_vin_querycap,
1806 .set_bus_param = rcar_vin_set_bus_param,
1807 .init_videobuf2 = rcar_vin_init_videobuf2,
1811 static struct of_device_id rcar_vin_of_table[] = {
1812 { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1813 { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
1814 { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1815 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1816 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1817 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1820 MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1823 static struct platform_device_id rcar_vin_id_table[] = {
1824 { "r8a7791-vin", RCAR_GEN2 },
1825 { "r8a7790-vin", RCAR_GEN2 },
1826 { "r8a7779-vin", RCAR_H1 },
1827 { "r8a7778-vin", RCAR_M1 },
1828 { "uPD35004-vin", RCAR_E1 },
1831 MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
1833 static int rcar_vin_probe(struct platform_device *pdev)
1835 const struct of_device_id *match = NULL;
1836 struct rcar_vin_priv *priv;
1837 struct resource *mem;
1838 struct rcar_vin_platform_data *pdata;
1839 unsigned int pdata_flags;
1842 if (pdev->dev.of_node) {
1843 struct v4l2_of_endpoint ep;
1844 struct device_node *np;
1846 match = of_match_device(of_match_ptr(rcar_vin_of_table),
1849 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1851 dev_err(&pdev->dev, "could not find endpoint\n");
1855 ret = v4l2_of_parse_endpoint(np, &ep);
1857 dev_err(&pdev->dev, "could not parse endpoint\n");
1861 if (ep.bus_type == V4L2_MBUS_BT656)
1862 pdata_flags = RCAR_VIN_BT656;
1865 if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1866 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1867 if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1868 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1873 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1875 pdata = pdev->dev.platform_data;
1876 if (!pdata || !pdata->flags) {
1877 dev_err(&pdev->dev, "platform data not set\n");
1880 pdata_flags = pdata->flags;
1883 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1887 irq = platform_get_irq(pdev, 0);
1891 priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1896 priv->base = devm_ioremap_resource(&pdev->dev, mem);
1897 if (IS_ERR(priv->base))
1898 return PTR_ERR(priv->base);
1900 ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1901 dev_name(&pdev->dev), priv);
1905 priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1906 if (IS_ERR(priv->alloc_ctx))
1907 return PTR_ERR(priv->alloc_ctx);
1909 priv->ici.priv = priv;
1910 priv->ici.v4l2_dev.dev = &pdev->dev;
1911 priv->ici.drv_name = dev_name(&pdev->dev);
1912 priv->ici.ops = &rcar_vin_host_ops;
1914 priv->pdata_flags = pdata_flags;
1916 priv->ici.nr = pdev->id;
1917 priv->chip = pdev->id_entry->driver_data;
1919 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1920 priv->chip = (enum chip_id)match->data;
1923 spin_lock_init(&priv->lock);
1924 INIT_LIST_HEAD(&priv->capture);
1926 priv->state = STOPPED;
1928 pm_suspend_ignore_children(&pdev->dev, true);
1929 pm_runtime_enable(&pdev->dev);
1931 ret = soc_camera_host_register(&priv->ici);
1938 pm_runtime_disable(&pdev->dev);
1939 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1944 static int rcar_vin_remove(struct platform_device *pdev)
1946 struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1947 struct rcar_vin_priv *priv = container_of(soc_host,
1948 struct rcar_vin_priv, ici);
1950 soc_camera_host_unregister(soc_host);
1951 pm_runtime_disable(&pdev->dev);
1952 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1957 static struct platform_driver rcar_vin_driver = {
1958 .probe = rcar_vin_probe,
1959 .remove = rcar_vin_remove,
1962 .of_match_table = of_match_ptr(rcar_vin_of_table),
1964 .id_table = rcar_vin_id_table,
1967 module_platform_driver(rcar_vin_driver);
1969 MODULE_LICENSE("GPL");
1970 MODULE_ALIAS("platform:rcar_vin");
1971 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");