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_device.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/slab.h>
27 #include <linux/videodev2.h>
29 #include <media/soc_camera.h>
30 #include <media/drv-intf/soc_mediabus.h>
31 #include <media/v4l2-common.h>
32 #include <media/v4l2-dev.h>
33 #include <media/v4l2-device.h>
34 #include <media/v4l2-mediabus.h>
35 #include <media/v4l2-of.h>
36 #include <media/v4l2-subdev.h>
37 #include <media/videobuf2-dma-contig.h>
39 #include "soc_scale_crop.h"
41 #define DRV_NAME "rcar_vin"
43 /* Register offsets for R-Car VIN */
44 #define VNMC_REG 0x00 /* Video n Main Control Register */
45 #define VNMS_REG 0x04 /* Video n Module Status Register */
46 #define VNFC_REG 0x08 /* Video n Frame Capture Register */
47 #define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */
48 #define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */
49 #define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */
50 #define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */
51 #define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */
52 #define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */
53 #define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */
54 #define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */
55 #define VNIS_REG 0x2C /* Video n Image Stride Register */
56 #define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
57 #define VNIE_REG 0x40 /* Video n Interrupt Enable Register */
58 #define VNINTS_REG 0x44 /* Video n Interrupt Status Register */
59 #define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */
60 #define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */
61 #define VNYS_REG 0x50 /* Video n Y Scale Register */
62 #define VNXS_REG 0x54 /* Video n X Scale Register */
63 #define VNDMR_REG 0x58 /* Video n Data Mode Register */
64 #define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */
65 #define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */
66 #define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */
67 #define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */
68 #define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */
69 #define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */
70 #define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */
71 #define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */
72 #define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */
73 #define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */
74 #define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */
75 #define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */
76 #define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */
77 #define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */
78 #define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */
79 #define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */
80 #define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */
81 #define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */
82 #define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */
83 #define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */
84 #define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */
85 #define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */
86 #define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */
87 #define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */
88 #define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */
89 #define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */
91 /* Register bit fields for R-Car VIN */
92 /* Video n Main Control Register bits */
93 #define VNMC_FOC (1 << 21)
94 #define VNMC_YCAL (1 << 19)
95 #define VNMC_INF_YUV8_BT656 (0 << 16)
96 #define VNMC_INF_YUV8_BT601 (1 << 16)
97 #define VNMC_INF_YUV10_BT656 (2 << 16)
98 #define VNMC_INF_YUV10_BT601 (3 << 16)
99 #define VNMC_INF_YUV16 (5 << 16)
100 #define VNMC_INF_RGB888 (6 << 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
140 #define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0)
141 #define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1)
142 #define RCAR_VIN_BT601 (1 << 2)
143 #define RCAR_VIN_BT656 (1 << 3)
153 unsigned short xs_value;
157 static const struct vin_coeff vin_coeff_set[] = {
159 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000,
162 0x00000000, 0x00000000, 0x00000000,
163 0x00000000, 0x00000000, 0x00000000,
164 0x00000000, 0x00000000, 0x00000000,
165 0x00000000, 0x00000000, 0x00000000,
166 0x00000000, 0x00000000, 0x00000000 },
169 0x000fa400, 0x000fa400, 0x09625902,
170 0x000003f8, 0x00000403, 0x3de0d9f0,
171 0x001fffed, 0x00000804, 0x3cc1f9c3,
172 0x001003de, 0x00000c01, 0x3cb34d7f,
173 0x002003d2, 0x00000c00, 0x3d24a92d,
174 0x00200bca, 0x00000bff, 0x3df600d2,
175 0x002013cc, 0x000007ff, 0x3ed70c7e,
176 0x00100fde, 0x00000000, 0x3f87c036 },
179 0x002ffff1, 0x002ffff1, 0x02a0a9c8,
180 0x002003e7, 0x001ffffa, 0x000185bc,
181 0x002007dc, 0x000003ff, 0x3e52859c,
182 0x00200bd4, 0x00000002, 0x3d53996b,
183 0x00100fd0, 0x00000403, 0x3d04ad2d,
184 0x00000bd5, 0x00000403, 0x3d35ace7,
185 0x3ff003e4, 0x00000801, 0x3dc674a1,
186 0x3fffe800, 0x00000800, 0x3e76f461 },
189 0x00100be3, 0x00100be3, 0x04d1359a,
190 0x00000fdb, 0x002003ed, 0x0211fd93,
191 0x00000fd6, 0x002003f4, 0x0002d97b,
192 0x000007d6, 0x002ffffb, 0x3e93b956,
193 0x3ff003da, 0x001003ff, 0x3db49926,
194 0x3fffefe9, 0x00100001, 0x3d655cee,
195 0x3fffd400, 0x00000003, 0x3d65f4b6,
196 0x000fb421, 0x00000402, 0x3dc6547e },
199 0x00000bdd, 0x00000bdd, 0x06519578,
200 0x3ff007da, 0x00000be3, 0x03c24973,
201 0x3ff003d9, 0x00000be9, 0x01b30d5f,
202 0x3ffff7df, 0x001003f1, 0x0003c542,
203 0x000fdfec, 0x001003f7, 0x3ec4711d,
204 0x000fc400, 0x002ffffd, 0x3df504f1,
205 0x001fa81a, 0x002ffc00, 0x3d957cc2,
206 0x002f8c3c, 0x00100000, 0x3db5c891 },
209 0x3ff003dc, 0x3ff003dc, 0x0791e558,
210 0x000ff7dd, 0x3ff007de, 0x05328554,
211 0x000fe7e3, 0x3ff00be2, 0x03232546,
212 0x000fd7ee, 0x000007e9, 0x0143bd30,
213 0x001fb800, 0x000007ee, 0x00044511,
214 0x002fa015, 0x000007f4, 0x3ef4bcee,
215 0x002f8832, 0x001003f9, 0x3e4514c7,
216 0x001f7853, 0x001003fd, 0x3de54c9f },
219 0x000fefe0, 0x000fefe0, 0x08721d3c,
220 0x001fdbe7, 0x000ffbde, 0x0652a139,
221 0x001fcbf0, 0x000003df, 0x0463292e,
222 0x002fb3ff, 0x3ff007e3, 0x0293a91d,
223 0x002f9c12, 0x3ff00be7, 0x01241905,
224 0x001f8c29, 0x000007ed, 0x3fe470eb,
225 0x000f7c46, 0x000007f2, 0x3f04b8ca,
226 0x3fef7865, 0x000007f6, 0x3e74e4a8 },
229 0x001fd3e9, 0x001fd3e9, 0x08f23d26,
230 0x002fbff3, 0x001fe3e4, 0x0712ad23,
231 0x002fa800, 0x000ff3e0, 0x05631d1b,
232 0x001f9810, 0x000ffbe1, 0x03b3890d,
233 0x000f8c23, 0x000003e3, 0x0233e8fa,
234 0x3fef843b, 0x000003e7, 0x00f430e4,
235 0x3fbf8456, 0x3ff00bea, 0x00046cc8,
236 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
239 0x001fbbf4, 0x001fbbf4, 0x09425112,
240 0x001fa800, 0x002fc7ed, 0x0792b110,
241 0x000f980e, 0x001fdbe6, 0x0613110a,
242 0x3fff8c20, 0x001fe7e3, 0x04a368fd,
243 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
244 0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
245 0x3f5f9c61, 0x000003e6, 0x00e428c5,
246 0x3f1fb07b, 0x000003eb, 0x3fe440af },
249 0x000fa400, 0x000fa400, 0x09625902,
250 0x3fff980c, 0x001fb7f5, 0x0812b0ff,
251 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
252 0x3faf902d, 0x001fd3e8, 0x055348f1,
253 0x3f7f983f, 0x001fe3e5, 0x04038ce3,
254 0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
255 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
256 0x3ecfd880, 0x000fffe6, 0x00c404ac },
259 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
260 0x3fbf9818, 0x3fffa400, 0x0842a8f1,
261 0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
262 0x3f5fa037, 0x000fc3ef, 0x05d330e4,
263 0x3f2fac49, 0x001fcfea, 0x04a364d9,
264 0x3effc05c, 0x001fdbe7, 0x038394ca,
265 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
266 0x3ea00083, 0x001fefe6, 0x0183c0a9 },
269 0x3f9fa014, 0x3f9fa014, 0x098260e6,
270 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
271 0x3f4fa431, 0x3fefa400, 0x0742d8e1,
272 0x3f1fb440, 0x3fffb3f8, 0x062310d9,
273 0x3eefc850, 0x000fbbf2, 0x050340d0,
274 0x3ecfe062, 0x000fcbec, 0x041364c2,
275 0x3ea00073, 0x001fd3ea, 0x03037cb5,
276 0x3e902086, 0x001fdfe8, 0x022388a5 },
279 0x3f5fa81e, 0x3f5fa81e, 0x096258da,
280 0x3f3fac2b, 0x3f8fa412, 0x088290d8,
281 0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
282 0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
283 0x3ecfe456, 0x3fefaffa, 0x05531cc6,
284 0x3eb00066, 0x3fffbbf3, 0x047334bb,
285 0x3ea01c77, 0x000fc7ee, 0x039348ae,
286 0x3ea04486, 0x000fd3eb, 0x02b350a1 },
289 0x3f2fb426, 0x3f2fb426, 0x094250ce,
290 0x3f0fc032, 0x3f4fac1b, 0x086284cd,
291 0x3eefd040, 0x3f7fa811, 0x0782acc9,
292 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
293 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
294 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
295 0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
296 0x3ec06884, 0x000fbff2, 0x03031c9e },
299 0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
300 0x3eefd439, 0x3f2fb822, 0x08526cc2,
301 0x3edfe845, 0x3f4fb018, 0x078294bf,
302 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
303 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
304 0x3ec0386b, 0x3fafac00, 0x0502e8ac,
305 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
306 0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
309 0x3eefdc31, 0x3eefdc31, 0x08e238b8,
310 0x3edfec3d, 0x3f0fc828, 0x082258b9,
311 0x3ed00049, 0x3f1fc01e, 0x077278b6,
312 0x3ed01455, 0x3f3fb815, 0x06c294b2,
313 0x3ed03460, 0x3f5fb40d, 0x0602acac,
314 0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
315 0x3f107476, 0x3f9fb400, 0x0472c89d,
316 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
319 0x3eefec37, 0x3eefec37, 0x088220b0,
320 0x3ee00041, 0x3effdc2d, 0x07f244ae,
321 0x3ee0144c, 0x3f0fd023, 0x07625cad,
322 0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
323 0x3f004861, 0x3f3fbc13, 0x060288a6,
324 0x3f20686b, 0x3f5fb80c, 0x05529c9e,
325 0x3f408c74, 0x3f6fb805, 0x04b2ac96,
326 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
329 0x3ef0003a, 0x3ef0003a, 0x084210a6,
330 0x3ef01045, 0x3effec32, 0x07b228a7,
331 0x3f00284e, 0x3f0fdc29, 0x073244a4,
332 0x3f104058, 0x3f0fd420, 0x06a258a2,
333 0x3f305c62, 0x3f2fc818, 0x0612689d,
334 0x3f508069, 0x3f3fc011, 0x05728496,
335 0x3f80a072, 0x3f4fc00a, 0x04d28c90,
336 0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
339 0x3f00103e, 0x3f00103e, 0x07f1fc9e,
340 0x3f102447, 0x3f000035, 0x0782149d,
341 0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
342 0x3f405458, 0x3f0fe424, 0x06924099,
343 0x3f607061, 0x3f1fd41d, 0x06024c97,
344 0x3f909068, 0x3f2fcc16, 0x05726490,
345 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
346 0x0000d077, 0x3f4fc409, 0x04627484 },
349 0x3f202040, 0x3f202040, 0x07a1e898,
350 0x3f303449, 0x3f100c38, 0x0741fc98,
351 0x3f504c50, 0x3f10002f, 0x06e21495,
352 0x3f706459, 0x3f1ff028, 0x06722492,
353 0x3fa08060, 0x3f1fe421, 0x05f2348f,
354 0x3fd09c67, 0x3f1fdc19, 0x05824c89,
355 0x0000bc6e, 0x3f2fd014, 0x04f25086,
356 0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
359 0x3f403042, 0x3f403042, 0x0761d890,
360 0x3f504848, 0x3f301c3b, 0x0701f090,
361 0x3f805c50, 0x3f200c33, 0x06a2008f,
362 0x3fa07458, 0x3f10002b, 0x06520c8d,
363 0x3fd0905e, 0x3f1ff424, 0x05e22089,
364 0x0000ac65, 0x3f1fe81d, 0x05823483,
365 0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
366 0x0080e871, 0x3f2fd412, 0x0482407c },
369 0x3f604043, 0x3f604043, 0x0721c88a,
370 0x3f80544a, 0x3f502c3c, 0x06d1d88a,
371 0x3fb06851, 0x3f301c35, 0x0681e889,
372 0x3fd08456, 0x3f30082f, 0x0611fc88,
373 0x00009c5d, 0x3f200027, 0x05d20884,
374 0x0030b863, 0x3f2ff421, 0x05621880,
375 0x0070d468, 0x3f2fe81b, 0x0502247c,
376 0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
379 0x3f904c44, 0x3f904c44, 0x06e1b884,
380 0x3fb0604a, 0x3f70383e, 0x0691c885,
381 0x3fe07451, 0x3f502c36, 0x0661d483,
382 0x00009055, 0x3f401831, 0x0601ec81,
383 0x0030a85b, 0x3f300c2a, 0x05b1f480,
384 0x0070c061, 0x3f300024, 0x0562047a,
385 0x00b0d867, 0x3f3ff41e, 0x05020c77,
386 0x00f0f46b, 0x3f2fec19, 0x04a21474 },
389 0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
390 0x3fe06c4b, 0x3f902c3f, 0x0681c081,
391 0x0000844f, 0x3f703838, 0x0631cc7d,
392 0x00309855, 0x3f602433, 0x05d1d47e,
393 0x0060b459, 0x3f50142e, 0x0581e47b,
394 0x00a0c85f, 0x3f400828, 0x0531f078,
395 0x00e0e064, 0x3f300021, 0x0501fc73,
396 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
399 0x3fe06444, 0x3fe06444, 0x0681a07a,
400 0x00007849, 0x3fc0503f, 0x0641b07a,
401 0x0020904d, 0x3fa0403a, 0x05f1c07a,
402 0x0060a453, 0x3f803034, 0x05c1c878,
403 0x0090b858, 0x3f70202f, 0x0571d477,
404 0x00d0d05d, 0x3f501829, 0x0531e073,
405 0x0110e462, 0x3f500825, 0x04e1e471,
406 0x01510065, 0x3f40001f, 0x04a1f06d },
409 0x00007044, 0x00007044, 0x06519476,
410 0x00208448, 0x3fe05c3f, 0x0621a476,
411 0x0050984d, 0x3fc04c3a, 0x05e1b075,
412 0x0080ac52, 0x3fa03c35, 0x05a1b875,
413 0x00c0c056, 0x3f803030, 0x0561c473,
414 0x0100d45b, 0x3f70202b, 0x0521d46f,
415 0x0140e860, 0x3f601427, 0x04d1d46e,
416 0x01810064, 0x3f500822, 0x0491dc6b },
419 0x0110a442, 0x0110a442, 0x0551545e,
420 0x0140b045, 0x00e0983f, 0x0531585f,
421 0x0160c047, 0x00c08c3c, 0x0511645e,
422 0x0190cc4a, 0x00908039, 0x04f1685f,
423 0x01c0dc4c, 0x00707436, 0x04d1705e,
424 0x0200e850, 0x00506833, 0x04b1785b,
425 0x0230f453, 0x00305c30, 0x0491805a,
426 0x02710056, 0x0010542d, 0x04718059 },
429 0x01c0bc40, 0x01c0bc40, 0x04c13052,
430 0x01e0c841, 0x01a0b43d, 0x04c13851,
431 0x0210cc44, 0x0180a83c, 0x04a13453,
432 0x0230d845, 0x0160a03a, 0x04913c52,
433 0x0260e047, 0x01409838, 0x04714052,
434 0x0280ec49, 0x01208c37, 0x04514c50,
435 0x02b0f44b, 0x01008435, 0x04414c50,
436 0x02d1004c, 0x00e07c33, 0x0431544f },
439 0x0230c83e, 0x0230c83e, 0x04711c4c,
440 0x0250d03f, 0x0210c43c, 0x0471204b,
441 0x0270d840, 0x0200b83c, 0x0451244b,
442 0x0290dc42, 0x01e0b43a, 0x0441244c,
443 0x02b0e443, 0x01c0b038, 0x0441284b,
444 0x02d0ec44, 0x01b0a438, 0x0421304a,
445 0x02f0f445, 0x0190a036, 0x04213449,
446 0x0310f847, 0x01709c34, 0x04213848 },
449 0x0280d03d, 0x0280d03d, 0x04310c48,
450 0x02a0d43e, 0x0270c83c, 0x04311047,
451 0x02b0dc3e, 0x0250c83a, 0x04311447,
452 0x02d0e040, 0x0240c03a, 0x04211446,
453 0x02e0e840, 0x0220bc39, 0x04111847,
454 0x0300e842, 0x0210b438, 0x04012445,
455 0x0310f043, 0x0200b037, 0x04012045,
456 0x0330f444, 0x01e0ac36, 0x03f12445 },
459 0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
460 0x0340e03a, 0x0330e039, 0x03c0f03e,
461 0x0350e03b, 0x0330dc39, 0x03c0ec3e,
462 0x0350e43a, 0x0320dc38, 0x03c0f43e,
463 0x0360e43b, 0x0320d839, 0x03b0f03e,
464 0x0360e83b, 0x0310d838, 0x03c0fc3b,
465 0x0370e83b, 0x0310d439, 0x03a0f83d,
466 0x0370e83c, 0x0300d438, 0x03b0fc3c },
470 enum rcar_vin_state {
476 struct rcar_vin_priv {
480 /* State of the VIN module in capturing mode */
481 enum rcar_vin_state state;
482 struct soc_camera_host ici;
483 struct list_head capture;
484 #define MAX_BUFFER_NUM 3
485 struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM];
486 struct vb2_alloc_ctx *alloc_ctx;
487 enum v4l2_field field;
488 unsigned int pdata_flags;
489 unsigned int vb_count;
490 unsigned int nr_hw_slots;
491 bool request_to_stop;
492 struct completion capture_stop;
496 #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
498 struct rcar_vin_buffer {
499 struct vb2_v4l2_buffer vb;
500 struct list_head list;
503 #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
504 struct rcar_vin_buffer, \
507 struct rcar_vin_cam {
508 /* VIN offsets within the camera output, before the VIN scaler */
509 unsigned int vin_left;
510 unsigned int vin_top;
511 /* Client output, as seen by the VIN */
514 /* User window from S_FMT */
515 unsigned int out_width;
516 unsigned int out_height;
518 * User window from S_CROP / G_CROP, produced by client cropping and
519 * scaling, VIN scaling and VIN cropping, mapped back onto the client
522 struct v4l2_rect subrect;
523 /* Camera cropping rectangle */
524 struct v4l2_rect rect;
525 const struct soc_mbus_pixelfmt *extra_fmt;
529 * .queue_setup() is called to check whether the driver can accept the requested
530 * number of buffers and to fill in plane sizes for the current frame format if
533 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
535 unsigned int *num_planes,
536 unsigned int sizes[], void *alloc_ctxs[])
538 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
539 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
540 struct rcar_vin_priv *priv = ici->priv;
542 alloc_ctxs[0] = priv->alloc_ctx;
544 if (!vq->num_buffers)
549 priv->vb_count = *count;
551 /* Number of hardware slots */
552 if (is_continuous_transfer(priv))
553 priv->nr_hw_slots = MAX_BUFFER_NUM;
555 priv->nr_hw_slots = 1;
558 return sizes[0] < icd->sizeimage ? -EINVAL : 0;
560 sizes[0] = icd->sizeimage;
563 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
568 static int rcar_vin_setup(struct rcar_vin_priv *priv)
570 struct soc_camera_device *icd = priv->ici.icd;
571 struct rcar_vin_cam *cam = icd->host_priv;
572 u32 vnmc, dmr, interrupts;
573 bool progressive = false, output_is_yuv = false, input_is_yuv = false;
575 switch (priv->field) {
579 case V4L2_FIELD_BOTTOM:
582 case V4L2_FIELD_INTERLACED:
583 case V4L2_FIELD_INTERLACED_TB:
586 case V4L2_FIELD_INTERLACED_BT:
587 vnmc = VNMC_IM_FULL | VNMC_FOC;
589 case V4L2_FIELD_NONE:
590 if (is_continuous_transfer(priv)) {
591 vnmc = VNMC_IM_ODD_EVEN;
602 /* input interface */
603 switch (icd->current_fmt->code) {
604 case MEDIA_BUS_FMT_YUYV8_1X16:
605 /* BT.601/BT.1358 16bit YCbCr422 */
606 vnmc |= VNMC_INF_YUV16;
609 case MEDIA_BUS_FMT_YUYV8_2X8:
610 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
611 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
612 VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
615 case MEDIA_BUS_FMT_RGB888_1X24:
616 vnmc |= VNMC_INF_RGB888;
618 case MEDIA_BUS_FMT_YUYV10_2X10:
619 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
620 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
621 VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
629 switch (icd->current_fmt->host_fmt->fourcc) {
630 case V4L2_PIX_FMT_NV16:
631 iowrite32(ALIGN(cam->width * cam->height, 0x80),
632 priv->base + VNUVAOF_REG);
633 dmr = VNDMR_DTMD_YCSEP;
634 output_is_yuv = true;
636 case V4L2_PIX_FMT_YUYV:
638 output_is_yuv = true;
640 case V4L2_PIX_FMT_UYVY:
642 output_is_yuv = true;
644 case V4L2_PIX_FMT_RGB555X:
645 dmr = VNDMR_DTMD_ARGB1555;
647 case V4L2_PIX_FMT_RGB565:
650 case V4L2_PIX_FMT_RGB32:
651 if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 ||
652 priv->chip == RCAR_E1) {
657 dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
658 icd->current_fmt->host_fmt->fourcc);
662 /* Always update on field change */
665 /* If input and output use the same colorspace, use bypass mode */
666 if (input_is_yuv == output_is_yuv)
669 /* progressive or interlaced mode */
670 interrupts = progressive ? VNIE_FIE : VNIE_EFE;
673 iowrite32(interrupts, priv->base + VNINTS_REG);
674 /* enable interrupts */
675 iowrite32(interrupts, priv->base + VNIE_REG);
676 /* start capturing */
677 iowrite32(dmr, priv->base + VNDMR_REG);
678 iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
683 static void rcar_vin_capture(struct rcar_vin_priv *priv)
685 if (is_continuous_transfer(priv))
686 /* Continuous Frame Capture Mode */
687 iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
689 /* Single Frame Capture Mode */
690 iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
693 static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
695 priv->state = STOPPING;
697 /* set continuous & single transfer off */
698 iowrite32(0, priv->base + VNFC_REG);
699 /* disable capture (release DMA buffer), reset */
700 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
701 priv->base + VNMC_REG);
703 /* update the status if stopped already */
704 if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
705 priv->state = STOPPED;
708 static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
712 for (slot = 0; slot < priv->nr_hw_slots; slot++)
713 if (priv->queue_buf[slot] == NULL)
719 static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
721 /* Ensure all HW slots are filled */
722 return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
725 /* Moves a buffer from the queue to the HW slots */
726 static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
728 struct vb2_v4l2_buffer *vbuf;
729 dma_addr_t phys_addr_top;
732 if (list_empty(&priv->capture))
735 /* Find a free HW slot */
736 slot = rcar_vin_get_free_hw_slot(priv);
740 vbuf = &list_entry(priv->capture.next,
741 struct rcar_vin_buffer, list)->vb;
742 list_del_init(to_buf_list(vbuf));
743 priv->queue_buf[slot] = vbuf;
744 phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
745 iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
750 static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
752 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
753 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
754 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
755 struct rcar_vin_priv *priv = ici->priv;
758 size = icd->sizeimage;
760 if (vb2_plane_size(vb, 0) < size) {
761 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
762 vb->index, vb2_plane_size(vb, 0), size);
766 vb2_set_plane_payload(vb, 0, size);
768 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
769 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
771 spin_lock_irq(&priv->lock);
773 list_add_tail(to_buf_list(vbuf), &priv->capture);
774 rcar_vin_fill_hw_slot(priv);
776 /* If we weren't running, and have enough buffers, start capturing! */
777 if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
778 if (rcar_vin_setup(priv)) {
780 list_del_init(to_buf_list(vbuf));
781 spin_unlock_irq(&priv->lock);
784 priv->request_to_stop = false;
785 init_completion(&priv->capture_stop);
786 priv->state = RUNNING;
787 rcar_vin_capture(priv);
790 spin_unlock_irq(&priv->lock);
795 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
799 * Wait for capture to stop and all in-flight buffers to be finished with by
800 * the video hardware. This must be called under &priv->lock
803 static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
805 while (priv->state != STOPPED) {
806 /* issue stop if running */
807 if (priv->state == RUNNING)
808 rcar_vin_request_capture_stop(priv);
810 /* wait until capturing has been stopped */
811 if (priv->state == STOPPING) {
812 priv->request_to_stop = true;
813 spin_unlock_irq(&priv->lock);
814 if (!wait_for_completion_timeout(
816 msecs_to_jiffies(TIMEOUT_MS)))
817 priv->state = STOPPED;
818 spin_lock_irq(&priv->lock);
823 static void rcar_vin_stop_streaming(struct vb2_queue *vq)
825 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
826 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
827 struct rcar_vin_priv *priv = ici->priv;
828 struct list_head *buf_head, *tmp;
831 spin_lock_irq(&priv->lock);
832 rcar_vin_wait_stop_streaming(priv);
834 for (i = 0; i < MAX_BUFFER_NUM; i++) {
835 if (priv->queue_buf[i]) {
836 vb2_buffer_done(&priv->queue_buf[i]->vb2_buf,
837 VB2_BUF_STATE_ERROR);
838 priv->queue_buf[i] = NULL;
842 list_for_each_safe(buf_head, tmp, &priv->capture) {
843 vb2_buffer_done(&list_entry(buf_head,
844 struct rcar_vin_buffer, list)->vb.vb2_buf,
845 VB2_BUF_STATE_ERROR);
846 list_del_init(buf_head);
848 spin_unlock_irq(&priv->lock);
851 static struct vb2_ops rcar_vin_vb2_ops = {
852 .queue_setup = rcar_vin_videobuf_setup,
853 .buf_queue = rcar_vin_videobuf_queue,
854 .stop_streaming = rcar_vin_stop_streaming,
855 .wait_prepare = vb2_ops_wait_prepare,
856 .wait_finish = vb2_ops_wait_finish,
859 static irqreturn_t rcar_vin_irq(int irq, void *data)
861 struct rcar_vin_priv *priv = data;
863 bool can_run = false, hw_stopped;
865 unsigned int handled = 0;
867 spin_lock(&priv->lock);
869 int_status = ioread32(priv->base + VNINTS_REG);
873 iowrite32(int_status, priv->base + VNINTS_REG);
876 /* nothing to do if capture status is 'STOPPED' */
877 if (priv->state == STOPPED)
880 hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
882 if (!priv->request_to_stop) {
883 if (is_continuous_transfer(priv))
884 slot = (ioread32(priv->base + VNMS_REG) &
885 VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
889 priv->queue_buf[slot]->field = priv->field;
890 priv->queue_buf[slot]->sequence = priv->sequence++;
891 priv->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
892 vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
894 priv->queue_buf[slot] = NULL;
896 if (priv->state != STOPPING)
897 can_run = rcar_vin_fill_hw_slot(priv);
899 if (hw_stopped || !can_run) {
900 priv->state = STOPPED;
901 } else if (is_continuous_transfer(priv) &&
902 list_empty(&priv->capture) &&
903 priv->state == RUNNING) {
905 * The continuous capturing requires an explicit stop
906 * operation when there is no buffer to be set into
907 * the VnMBm registers.
909 rcar_vin_request_capture_stop(priv);
911 rcar_vin_capture(priv);
914 } else if (hw_stopped) {
915 priv->state = STOPPED;
916 priv->request_to_stop = false;
917 complete(&priv->capture_stop);
921 spin_unlock(&priv->lock);
923 return IRQ_RETVAL(handled);
926 static int rcar_vin_add_device(struct soc_camera_device *icd)
928 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
929 struct rcar_vin_priv *priv = ici->priv;
932 for (i = 0; i < MAX_BUFFER_NUM; i++)
933 priv->queue_buf[i] = NULL;
935 pm_runtime_get_sync(ici->v4l2_dev.dev);
937 dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
943 static void rcar_vin_remove_device(struct soc_camera_device *icd)
945 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
946 struct rcar_vin_priv *priv = ici->priv;
947 struct vb2_v4l2_buffer *vbuf;
950 /* disable capture, disable interrupts */
951 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
952 priv->base + VNMC_REG);
953 iowrite32(0, priv->base + VNIE_REG);
955 priv->state = STOPPED;
956 priv->request_to_stop = false;
958 /* make sure active buffer is cancelled */
959 spin_lock_irq(&priv->lock);
960 for (i = 0; i < MAX_BUFFER_NUM; i++) {
961 vbuf = priv->queue_buf[i];
963 list_del_init(to_buf_list(vbuf));
964 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
967 spin_unlock_irq(&priv->lock);
969 pm_runtime_put(ici->v4l2_dev.dev);
971 dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
975 static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
978 const struct vin_coeff *p_prev_set = NULL;
979 const struct vin_coeff *p_set = NULL;
981 /* Look for suitable coefficient values */
982 for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
984 p_set = &vin_coeff_set[i];
986 if (xs < p_set->xs_value)
990 /* Use previous value if its XS value is closer */
991 if (p_prev_set && p_set &&
992 xs - p_prev_set->xs_value < p_set->xs_value - xs)
995 /* Set coefficient registers */
996 iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
997 iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
998 iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
1000 iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
1001 iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
1002 iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
1004 iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
1005 iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
1006 iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
1008 iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
1009 iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
1010 iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
1012 iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
1013 iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
1014 iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
1016 iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
1017 iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
1018 iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
1020 iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
1021 iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
1022 iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
1024 iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
1025 iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
1026 iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
1029 /* rect is guaranteed to not exceed the scaled camera rectangle */
1030 static int rcar_vin_set_rect(struct soc_camera_device *icd)
1032 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1033 struct rcar_vin_cam *cam = icd->host_priv;
1034 struct rcar_vin_priv *priv = ici->priv;
1035 unsigned int left_offset, top_offset;
1036 unsigned char dsize = 0;
1037 struct v4l2_rect *cam_subrect = &cam->subrect;
1040 dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
1041 icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
1043 left_offset = cam->vin_left;
1044 top_offset = cam->vin_top;
1046 if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 &&
1047 priv->chip == RCAR_E1)
1050 dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
1051 cam->width, cam->height, cam->vin_left, cam->vin_top);
1052 dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
1053 cam_subrect->width, cam_subrect->height,
1054 cam_subrect->left, cam_subrect->top);
1056 /* Set Start/End Pixel/Line Pre-Clip */
1057 iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
1058 iowrite32((left_offset + cam_subrect->width - 1) << dsize,
1059 priv->base + VNEPPRC_REG);
1060 switch (priv->field) {
1061 case V4L2_FIELD_INTERLACED:
1062 case V4L2_FIELD_INTERLACED_TB:
1063 case V4L2_FIELD_INTERLACED_BT:
1064 iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
1065 iowrite32((top_offset + cam_subrect->height) / 2 - 1,
1066 priv->base + VNELPRC_REG);
1069 iowrite32(top_offset, priv->base + VNSLPRC_REG);
1070 iowrite32(top_offset + cam_subrect->height - 1,
1071 priv->base + VNELPRC_REG);
1075 /* Set scaling coefficient */
1077 if (cam_subrect->height != cam->out_height)
1078 value = (4096 * cam_subrect->height) / cam->out_height;
1079 dev_dbg(icd->parent, "YS Value: %x\n", value);
1080 iowrite32(value, priv->base + VNYS_REG);
1083 if (cam_subrect->width != cam->out_width)
1084 value = (4096 * cam_subrect->width) / cam->out_width;
1086 /* Horizontal upscaling is up to double size */
1087 if (0 < value && value < 2048)
1090 dev_dbg(icd->parent, "XS Value: %x\n", value);
1091 iowrite32(value, priv->base + VNXS_REG);
1093 /* Horizontal upscaling is carried out by scaling down from double size */
1097 set_coeff(priv, value);
1099 /* Set Start/End Pixel/Line Post-Clip */
1100 iowrite32(0, priv->base + VNSPPOC_REG);
1101 iowrite32(0, priv->base + VNSLPOC_REG);
1102 iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
1103 switch (priv->field) {
1104 case V4L2_FIELD_INTERLACED:
1105 case V4L2_FIELD_INTERLACED_TB:
1106 case V4L2_FIELD_INTERLACED_BT:
1107 iowrite32(cam->out_height / 2 - 1,
1108 priv->base + VNELPOC_REG);
1111 iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
1115 iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
1120 static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
1122 *vnmc = ioread32(priv->base + VNMC_REG);
1123 /* module disable */
1124 iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
1127 static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
1129 unsigned long timeout = jiffies + 10 * HZ;
1132 * Wait until the end of the current frame. It can take a long time,
1133 * but if it has been aborted by a MRST1 reset, it should exit sooner.
1135 while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
1136 time_before(jiffies, timeout))
1139 if (time_after(jiffies, timeout)) {
1140 dev_err(priv->ici.v4l2_dev.dev,
1141 "Timeout waiting for frame end! Interface problem?\n");
1145 iowrite32(vnmc, priv->base + VNMC_REG);
1148 #define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \
1149 V4L2_MBUS_PCLK_SAMPLE_RISING | \
1150 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
1151 V4L2_MBUS_HSYNC_ACTIVE_LOW | \
1152 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
1153 V4L2_MBUS_VSYNC_ACTIVE_LOW | \
1154 V4L2_MBUS_DATA_ACTIVE_HIGH)
1156 static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
1158 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1159 struct rcar_vin_priv *priv = ici->priv;
1160 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1161 struct v4l2_mbus_config cfg;
1162 unsigned long common_flags;
1167 capture_stop_preserve(priv, &vnmc);
1169 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1171 common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1172 if (!common_flags) {
1173 dev_warn(icd->parent,
1174 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1175 cfg.flags, VIN_MBUS_FLAGS);
1178 } else if (ret != -ENOIOCTLCMD) {
1181 common_flags = VIN_MBUS_FLAGS;
1184 /* Make choises, based on platform preferences */
1185 if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1186 (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
1187 if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
1188 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1190 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1193 if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1194 (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
1195 if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
1196 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1198 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1201 cfg.flags = common_flags;
1202 ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1203 if (ret < 0 && ret != -ENOIOCTLCMD)
1206 val = VNDMR2_FTEV | VNDMR2_VLV(1);
1207 if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
1209 if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
1211 iowrite32(val, priv->base + VNDMR2_REG);
1213 ret = rcar_vin_set_rect(icd);
1217 capture_restore(priv, vnmc);
1222 static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
1223 unsigned char buswidth)
1225 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1226 struct v4l2_mbus_config cfg;
1229 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1230 if (ret == -ENOIOCTLCMD)
1238 /* check is there common mbus flags */
1239 ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1243 dev_warn(icd->parent,
1244 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1245 cfg.flags, VIN_MBUS_FLAGS);
1250 static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1252 return fmt->packing == SOC_MBUS_PACKING_NONE ||
1253 (fmt->bits_per_sample > 8 &&
1254 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1257 static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
1259 .fourcc = V4L2_PIX_FMT_NV16,
1261 .bits_per_sample = 8,
1262 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1263 .order = SOC_MBUS_ORDER_LE,
1264 .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
1267 .fourcc = V4L2_PIX_FMT_YUYV,
1269 .bits_per_sample = 16,
1270 .packing = SOC_MBUS_PACKING_NONE,
1271 .order = SOC_MBUS_ORDER_LE,
1272 .layout = SOC_MBUS_LAYOUT_PACKED,
1275 .fourcc = V4L2_PIX_FMT_UYVY,
1277 .bits_per_sample = 16,
1278 .packing = SOC_MBUS_PACKING_NONE,
1279 .order = SOC_MBUS_ORDER_LE,
1280 .layout = SOC_MBUS_LAYOUT_PACKED,
1283 .fourcc = V4L2_PIX_FMT_RGB565,
1285 .bits_per_sample = 16,
1286 .packing = SOC_MBUS_PACKING_NONE,
1287 .order = SOC_MBUS_ORDER_LE,
1288 .layout = SOC_MBUS_LAYOUT_PACKED,
1291 .fourcc = V4L2_PIX_FMT_RGB555X,
1293 .bits_per_sample = 16,
1294 .packing = SOC_MBUS_PACKING_NONE,
1295 .order = SOC_MBUS_ORDER_LE,
1296 .layout = SOC_MBUS_LAYOUT_PACKED,
1299 .fourcc = V4L2_PIX_FMT_RGB32,
1301 .bits_per_sample = 32,
1302 .packing = SOC_MBUS_PACKING_NONE,
1303 .order = SOC_MBUS_ORDER_LE,
1304 .layout = SOC_MBUS_LAYOUT_PACKED,
1308 static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
1309 struct soc_camera_format_xlate *xlate)
1311 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1312 struct device *dev = icd->parent;
1315 struct rcar_vin_cam *cam;
1316 struct v4l2_subdev_mbus_code_enum code = {
1317 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1320 const struct soc_mbus_pixelfmt *fmt;
1322 ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
1326 fmt = soc_mbus_get_fmtdesc(code.code);
1328 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
1332 ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1336 if (!icd->host_priv) {
1337 struct v4l2_subdev_format fmt = {
1338 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1340 struct v4l2_mbus_framefmt *mf = &fmt.format;
1341 struct v4l2_rect rect;
1342 struct device *dev = icd->parent;
1345 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1349 /* Cache current client geometry */
1350 ret = soc_camera_client_g_rect(sd, &rect);
1351 if (ret == -ENOIOCTLCMD) {
1352 /* Sensor driver doesn't support cropping */
1355 rect.width = mf->width;
1356 rect.height = mf->height;
1357 } else if (ret < 0) {
1362 * If sensor proposes too large format then try smaller ones:
1363 * 1280x960, 640x480, 320x240
1365 for (shift = 0; shift < 3; shift++) {
1366 if (mf->width <= VIN_MAX_WIDTH &&
1367 mf->height <= VIN_MAX_HEIGHT)
1370 mf->width = 1280 >> shift;
1371 mf->height = 960 >> shift;
1372 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1373 soc_camera_grp_id(icd),
1382 "Failed to configure the client below %ux%u\n",
1383 mf->width, mf->height);
1387 dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
1389 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1393 * We are called with current camera crop,
1394 * initialise subrect with it
1397 cam->subrect = rect;
1398 cam->width = mf->width;
1399 cam->height = mf->height;
1400 cam->out_width = mf->width;
1401 cam->out_height = mf->height;
1403 icd->host_priv = cam;
1405 cam = icd->host_priv;
1408 /* Beginning of a pass */
1410 cam->extra_fmt = NULL;
1412 switch (code.code) {
1413 case MEDIA_BUS_FMT_YUYV8_1X16:
1414 case MEDIA_BUS_FMT_YUYV8_2X8:
1415 case MEDIA_BUS_FMT_YUYV10_2X10:
1416 case MEDIA_BUS_FMT_RGB888_1X24:
1420 /* Add all our formats that can be generated by VIN */
1421 cam->extra_fmt = rcar_vin_formats;
1423 n = ARRAY_SIZE(rcar_vin_formats);
1425 for (k = 0; xlate && k < n; k++, xlate++) {
1426 xlate->host_fmt = &rcar_vin_formats[k];
1427 xlate->code = code.code;
1428 dev_dbg(dev, "Providing format %s using code %d\n",
1429 rcar_vin_formats[k].name, code.code);
1433 if (!rcar_vin_packing_supported(fmt))
1436 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1441 /* Generic pass-through */
1444 xlate->host_fmt = fmt;
1445 xlate->code = code.code;
1452 static void rcar_vin_put_formats(struct soc_camera_device *icd)
1454 kfree(icd->host_priv);
1455 icd->host_priv = NULL;
1458 static int rcar_vin_set_crop(struct soc_camera_device *icd,
1459 const struct v4l2_crop *a)
1461 struct v4l2_crop a_writable = *a;
1462 const struct v4l2_rect *rect = &a_writable.c;
1463 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1464 struct rcar_vin_priv *priv = ici->priv;
1465 struct v4l2_crop cam_crop;
1466 struct rcar_vin_cam *cam = icd->host_priv;
1467 struct v4l2_rect *cam_rect = &cam_crop.c;
1468 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1469 struct device *dev = icd->parent;
1470 struct v4l2_subdev_format fmt = {
1471 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1473 struct v4l2_mbus_framefmt *mf = &fmt.format;
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, pad, get_fmt, NULL, &fmt);
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);
1585 if (ret == -ENOIOCTLCMD) {
1586 field = V4L2_FIELD_NONE;
1587 } else if (ret < 0) {
1590 field = std & V4L2_STD_625_50 ?
1591 V4L2_FIELD_INTERLACED_TB :
1592 V4L2_FIELD_INTERLACED_BT;
1597 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1599 dev_warn(dev, "Format %x not found\n", pixfmt);
1602 /* Calculate client output geometry */
1603 soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1605 mf.field = pix->field;
1606 mf.colorspace = pix->colorspace;
1607 mf.code = xlate->code;
1610 case V4L2_PIX_FMT_RGB32:
1611 can_scale = priv->chip != RCAR_E1;
1613 case V4L2_PIX_FMT_UYVY:
1614 case V4L2_PIX_FMT_YUYV:
1615 case V4L2_PIX_FMT_RGB565:
1616 case V4L2_PIX_FMT_RGB555X:
1624 dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1626 ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1627 &mf, &vin_sub_width, &vin_sub_height,
1630 /* Done with the camera. Now see if we can improve the result */
1631 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1632 ret, mf.width, mf.height, pix->width, pix->height);
1634 if (ret == -ENOIOCTLCMD)
1635 dev_dbg(dev, "Sensor doesn't support scaling\n");
1639 if (mf.code != xlate->code)
1642 /* Prepare VIN crop */
1643 cam->width = mf.width;
1644 cam->height = mf.height;
1646 /* Use VIN scaling to scale to the requested user window. */
1648 /* We cannot scale up */
1649 if (pix->width > vin_sub_width)
1650 vin_sub_width = pix->width;
1652 if (pix->height > vin_sub_height)
1653 vin_sub_height = pix->height;
1655 pix->colorspace = mf.colorspace;
1658 pix->width = vin_sub_width;
1659 pix->height = vin_sub_height;
1663 * We have calculated CFLCR, the actual configuration will be performed
1664 * in rcar_vin_set_bus_param()
1667 dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1668 vin_sub_width, pix->width, vin_sub_height, pix->height);
1670 cam->out_width = pix->width;
1671 cam->out_height = pix->height;
1673 icd->current_fmt = xlate;
1675 priv->field = field;
1680 static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1681 struct v4l2_format *f)
1683 const struct soc_camera_format_xlate *xlate;
1684 struct v4l2_pix_format *pix = &f->fmt.pix;
1685 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1686 struct v4l2_subdev_pad_config pad_cfg;
1687 struct v4l2_subdev_format format = {
1688 .which = V4L2_SUBDEV_FORMAT_TRY,
1690 struct v4l2_mbus_framefmt *mf = &format.format;
1691 __u32 pixfmt = pix->pixelformat;
1695 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1697 xlate = icd->current_fmt;
1698 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1699 pixfmt, xlate->host_fmt->fourcc);
1700 pixfmt = xlate->host_fmt->fourcc;
1701 pix->pixelformat = pixfmt;
1702 pix->colorspace = icd->colorspace;
1705 /* FIXME: calculate using depth and bus width */
1706 v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1707 &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1710 height = pix->height;
1712 /* let soc-camera calculate these values */
1713 pix->bytesperline = 0;
1716 /* limit to sensor capabilities */
1717 mf->width = pix->width;
1718 mf->height = pix->height;
1719 mf->field = pix->field;
1720 mf->code = xlate->code;
1721 mf->colorspace = pix->colorspace;
1723 ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
1724 pad, set_fmt, &pad_cfg, &format);
1728 /* Adjust only if VIN cannot scale */
1729 if (pix->width > mf->width * 2)
1730 pix->width = mf->width * 2;
1731 if (pix->height > mf->height * 3)
1732 pix->height = mf->height * 3;
1734 pix->field = mf->field;
1735 pix->colorspace = mf->colorspace;
1737 if (pixfmt == V4L2_PIX_FMT_NV16) {
1738 /* FIXME: check against rect_max after converting soc-camera */
1739 /* We can scale precisely, need a bigger image from camera */
1740 if (pix->width < width || pix->height < height) {
1742 * We presume, the sensor behaves sanely, i.e. if
1743 * requested a bigger rectangle, it will not return a
1746 mf->width = VIN_MAX_WIDTH;
1747 mf->height = VIN_MAX_HEIGHT;
1748 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1749 soc_camera_grp_id(icd),
1750 pad, set_fmt, &pad_cfg,
1753 dev_err(icd->parent,
1754 "client try_fmt() = %d\n", ret);
1758 /* We will scale exactly */
1759 if (mf->width > width)
1761 if (mf->height > height)
1762 pix->height = height;
1768 static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1770 struct soc_camera_device *icd = file->private_data;
1772 return vb2_poll(&icd->vb2_vidq, file, pt);
1775 static int rcar_vin_querycap(struct soc_camera_host *ici,
1776 struct v4l2_capability *cap)
1778 strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
1779 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1780 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1781 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr);
1786 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1787 struct soc_camera_device *icd)
1789 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1791 vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1792 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1794 vq->ops = &rcar_vin_vb2_ops;
1795 vq->mem_ops = &vb2_dma_contig_memops;
1796 vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
1797 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1798 vq->lock = &ici->host_lock;
1800 return vb2_queue_init(vq);
1803 static struct soc_camera_host_ops rcar_vin_host_ops = {
1804 .owner = THIS_MODULE,
1805 .add = rcar_vin_add_device,
1806 .remove = rcar_vin_remove_device,
1807 .get_formats = rcar_vin_get_formats,
1808 .put_formats = rcar_vin_put_formats,
1809 .get_crop = rcar_vin_get_crop,
1810 .set_crop = rcar_vin_set_crop,
1811 .try_fmt = rcar_vin_try_fmt,
1812 .set_fmt = rcar_vin_set_fmt,
1813 .poll = rcar_vin_poll,
1814 .querycap = rcar_vin_querycap,
1815 .set_bus_param = rcar_vin_set_bus_param,
1816 .init_videobuf2 = rcar_vin_init_videobuf2,
1820 static const struct of_device_id rcar_vin_of_table[] = {
1821 { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1822 { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
1823 { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1824 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1825 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1826 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1829 MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1832 static int rcar_vin_probe(struct platform_device *pdev)
1834 const struct of_device_id *match = NULL;
1835 struct rcar_vin_priv *priv;
1836 struct v4l2_of_endpoint ep;
1837 struct device_node *np;
1838 struct resource *mem;
1839 unsigned int pdata_flags;
1842 match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev);
1844 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1846 dev_err(&pdev->dev, "could not find endpoint\n");
1850 ret = v4l2_of_parse_endpoint(np, &ep);
1852 dev_err(&pdev->dev, "could not parse endpoint\n");
1856 if (ep.bus_type == V4L2_MBUS_BT656)
1857 pdata_flags = RCAR_VIN_BT656;
1860 if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1861 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1862 if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1863 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1868 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1870 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1874 irq = platform_get_irq(pdev, 0);
1878 priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1883 priv->base = devm_ioremap_resource(&pdev->dev, mem);
1884 if (IS_ERR(priv->base))
1885 return PTR_ERR(priv->base);
1887 ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1888 dev_name(&pdev->dev), priv);
1892 priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1893 if (IS_ERR(priv->alloc_ctx))
1894 return PTR_ERR(priv->alloc_ctx);
1896 priv->ici.priv = priv;
1897 priv->ici.v4l2_dev.dev = &pdev->dev;
1898 priv->ici.drv_name = dev_name(&pdev->dev);
1899 priv->ici.ops = &rcar_vin_host_ops;
1901 priv->pdata_flags = pdata_flags;
1903 priv->ici.nr = pdev->id;
1904 priv->chip = pdev->id_entry->driver_data;
1906 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1907 priv->chip = (enum chip_id)match->data;
1910 spin_lock_init(&priv->lock);
1911 INIT_LIST_HEAD(&priv->capture);
1913 priv->state = STOPPED;
1915 pm_suspend_ignore_children(&pdev->dev, true);
1916 pm_runtime_enable(&pdev->dev);
1918 ret = soc_camera_host_register(&priv->ici);
1925 pm_runtime_disable(&pdev->dev);
1926 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1931 static int rcar_vin_remove(struct platform_device *pdev)
1933 struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1934 struct rcar_vin_priv *priv = container_of(soc_host,
1935 struct rcar_vin_priv, ici);
1937 soc_camera_host_unregister(soc_host);
1938 pm_runtime_disable(&pdev->dev);
1939 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1944 static struct platform_driver rcar_vin_driver = {
1945 .probe = rcar_vin_probe,
1946 .remove = rcar_vin_remove,
1949 .of_match_table = of_match_ptr(rcar_vin_of_table),
1953 module_platform_driver(rcar_vin_driver);
1955 MODULE_LICENSE("GPL");
1956 MODULE_ALIAS("platform:rcar_vin");
1957 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");