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_INF_RGB888 (6 << 16)
102 #define VNMC_VUP (1 << 10)
103 #define VNMC_IM_ODD (0 << 3)
104 #define VNMC_IM_ODD_EVEN (1 << 3)
105 #define VNMC_IM_EVEN (2 << 3)
106 #define VNMC_IM_FULL (3 << 3)
107 #define VNMC_BPS (1 << 1)
108 #define VNMC_ME (1 << 0)
110 /* Video n Module Status Register bits */
111 #define VNMS_FBS_MASK (3 << 3)
112 #define VNMS_FBS_SHIFT 3
113 #define VNMS_AV (1 << 1)
114 #define VNMS_CA (1 << 0)
116 /* Video n Frame Capture Register bits */
117 #define VNFC_C_FRAME (1 << 1)
118 #define VNFC_S_FRAME (1 << 0)
120 /* Video n Interrupt Enable Register bits */
121 #define VNIE_FIE (1 << 4)
122 #define VNIE_EFE (1 << 1)
124 /* Video n Data Mode Register bits */
125 #define VNDMR_EXRGB (1 << 8)
126 #define VNDMR_BPSM (1 << 4)
127 #define VNDMR_DTMD_YCSEP (1 << 1)
128 #define VNDMR_DTMD_ARGB1555 (1 << 0)
130 /* Video n Data Mode Register 2 bits */
131 #define VNDMR2_VPS (1 << 30)
132 #define VNDMR2_HPS (1 << 29)
133 #define VNDMR2_FTEV (1 << 17)
134 #define VNDMR2_VLV(n) ((n & 0xf) << 12)
136 #define VIN_MAX_WIDTH 2048
137 #define VIN_MAX_HEIGHT 2048
139 #define TIMEOUT_MS 100
149 unsigned short xs_value;
153 static const struct vin_coeff vin_coeff_set[] = {
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,
162 0x00000000, 0x00000000, 0x00000000 },
165 0x000fa400, 0x000fa400, 0x09625902,
166 0x000003f8, 0x00000403, 0x3de0d9f0,
167 0x001fffed, 0x00000804, 0x3cc1f9c3,
168 0x001003de, 0x00000c01, 0x3cb34d7f,
169 0x002003d2, 0x00000c00, 0x3d24a92d,
170 0x00200bca, 0x00000bff, 0x3df600d2,
171 0x002013cc, 0x000007ff, 0x3ed70c7e,
172 0x00100fde, 0x00000000, 0x3f87c036 },
175 0x002ffff1, 0x002ffff1, 0x02a0a9c8,
176 0x002003e7, 0x001ffffa, 0x000185bc,
177 0x002007dc, 0x000003ff, 0x3e52859c,
178 0x00200bd4, 0x00000002, 0x3d53996b,
179 0x00100fd0, 0x00000403, 0x3d04ad2d,
180 0x00000bd5, 0x00000403, 0x3d35ace7,
181 0x3ff003e4, 0x00000801, 0x3dc674a1,
182 0x3fffe800, 0x00000800, 0x3e76f461 },
185 0x00100be3, 0x00100be3, 0x04d1359a,
186 0x00000fdb, 0x002003ed, 0x0211fd93,
187 0x00000fd6, 0x002003f4, 0x0002d97b,
188 0x000007d6, 0x002ffffb, 0x3e93b956,
189 0x3ff003da, 0x001003ff, 0x3db49926,
190 0x3fffefe9, 0x00100001, 0x3d655cee,
191 0x3fffd400, 0x00000003, 0x3d65f4b6,
192 0x000fb421, 0x00000402, 0x3dc6547e },
195 0x00000bdd, 0x00000bdd, 0x06519578,
196 0x3ff007da, 0x00000be3, 0x03c24973,
197 0x3ff003d9, 0x00000be9, 0x01b30d5f,
198 0x3ffff7df, 0x001003f1, 0x0003c542,
199 0x000fdfec, 0x001003f7, 0x3ec4711d,
200 0x000fc400, 0x002ffffd, 0x3df504f1,
201 0x001fa81a, 0x002ffc00, 0x3d957cc2,
202 0x002f8c3c, 0x00100000, 0x3db5c891 },
205 0x3ff003dc, 0x3ff003dc, 0x0791e558,
206 0x000ff7dd, 0x3ff007de, 0x05328554,
207 0x000fe7e3, 0x3ff00be2, 0x03232546,
208 0x000fd7ee, 0x000007e9, 0x0143bd30,
209 0x001fb800, 0x000007ee, 0x00044511,
210 0x002fa015, 0x000007f4, 0x3ef4bcee,
211 0x002f8832, 0x001003f9, 0x3e4514c7,
212 0x001f7853, 0x001003fd, 0x3de54c9f },
215 0x000fefe0, 0x000fefe0, 0x08721d3c,
216 0x001fdbe7, 0x000ffbde, 0x0652a139,
217 0x001fcbf0, 0x000003df, 0x0463292e,
218 0x002fb3ff, 0x3ff007e3, 0x0293a91d,
219 0x002f9c12, 0x3ff00be7, 0x01241905,
220 0x001f8c29, 0x000007ed, 0x3fe470eb,
221 0x000f7c46, 0x000007f2, 0x3f04b8ca,
222 0x3fef7865, 0x000007f6, 0x3e74e4a8 },
225 0x001fd3e9, 0x001fd3e9, 0x08f23d26,
226 0x002fbff3, 0x001fe3e4, 0x0712ad23,
227 0x002fa800, 0x000ff3e0, 0x05631d1b,
228 0x001f9810, 0x000ffbe1, 0x03b3890d,
229 0x000f8c23, 0x000003e3, 0x0233e8fa,
230 0x3fef843b, 0x000003e7, 0x00f430e4,
231 0x3fbf8456, 0x3ff00bea, 0x00046cc8,
232 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
235 0x001fbbf4, 0x001fbbf4, 0x09425112,
236 0x001fa800, 0x002fc7ed, 0x0792b110,
237 0x000f980e, 0x001fdbe6, 0x0613110a,
238 0x3fff8c20, 0x001fe7e3, 0x04a368fd,
239 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
240 0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
241 0x3f5f9c61, 0x000003e6, 0x00e428c5,
242 0x3f1fb07b, 0x000003eb, 0x3fe440af },
245 0x000fa400, 0x000fa400, 0x09625902,
246 0x3fff980c, 0x001fb7f5, 0x0812b0ff,
247 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
248 0x3faf902d, 0x001fd3e8, 0x055348f1,
249 0x3f7f983f, 0x001fe3e5, 0x04038ce3,
250 0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
251 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
252 0x3ecfd880, 0x000fffe6, 0x00c404ac },
255 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
256 0x3fbf9818, 0x3fffa400, 0x0842a8f1,
257 0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
258 0x3f5fa037, 0x000fc3ef, 0x05d330e4,
259 0x3f2fac49, 0x001fcfea, 0x04a364d9,
260 0x3effc05c, 0x001fdbe7, 0x038394ca,
261 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
262 0x3ea00083, 0x001fefe6, 0x0183c0a9 },
265 0x3f9fa014, 0x3f9fa014, 0x098260e6,
266 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
267 0x3f4fa431, 0x3fefa400, 0x0742d8e1,
268 0x3f1fb440, 0x3fffb3f8, 0x062310d9,
269 0x3eefc850, 0x000fbbf2, 0x050340d0,
270 0x3ecfe062, 0x000fcbec, 0x041364c2,
271 0x3ea00073, 0x001fd3ea, 0x03037cb5,
272 0x3e902086, 0x001fdfe8, 0x022388a5 },
275 0x3f5fa81e, 0x3f5fa81e, 0x096258da,
276 0x3f3fac2b, 0x3f8fa412, 0x088290d8,
277 0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
278 0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
279 0x3ecfe456, 0x3fefaffa, 0x05531cc6,
280 0x3eb00066, 0x3fffbbf3, 0x047334bb,
281 0x3ea01c77, 0x000fc7ee, 0x039348ae,
282 0x3ea04486, 0x000fd3eb, 0x02b350a1 },
285 0x3f2fb426, 0x3f2fb426, 0x094250ce,
286 0x3f0fc032, 0x3f4fac1b, 0x086284cd,
287 0x3eefd040, 0x3f7fa811, 0x0782acc9,
288 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
289 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
290 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
291 0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
292 0x3ec06884, 0x000fbff2, 0x03031c9e },
295 0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
296 0x3eefd439, 0x3f2fb822, 0x08526cc2,
297 0x3edfe845, 0x3f4fb018, 0x078294bf,
298 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
299 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
300 0x3ec0386b, 0x3fafac00, 0x0502e8ac,
301 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
302 0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
305 0x3eefdc31, 0x3eefdc31, 0x08e238b8,
306 0x3edfec3d, 0x3f0fc828, 0x082258b9,
307 0x3ed00049, 0x3f1fc01e, 0x077278b6,
308 0x3ed01455, 0x3f3fb815, 0x06c294b2,
309 0x3ed03460, 0x3f5fb40d, 0x0602acac,
310 0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
311 0x3f107476, 0x3f9fb400, 0x0472c89d,
312 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
315 0x3eefec37, 0x3eefec37, 0x088220b0,
316 0x3ee00041, 0x3effdc2d, 0x07f244ae,
317 0x3ee0144c, 0x3f0fd023, 0x07625cad,
318 0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
319 0x3f004861, 0x3f3fbc13, 0x060288a6,
320 0x3f20686b, 0x3f5fb80c, 0x05529c9e,
321 0x3f408c74, 0x3f6fb805, 0x04b2ac96,
322 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
325 0x3ef0003a, 0x3ef0003a, 0x084210a6,
326 0x3ef01045, 0x3effec32, 0x07b228a7,
327 0x3f00284e, 0x3f0fdc29, 0x073244a4,
328 0x3f104058, 0x3f0fd420, 0x06a258a2,
329 0x3f305c62, 0x3f2fc818, 0x0612689d,
330 0x3f508069, 0x3f3fc011, 0x05728496,
331 0x3f80a072, 0x3f4fc00a, 0x04d28c90,
332 0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
335 0x3f00103e, 0x3f00103e, 0x07f1fc9e,
336 0x3f102447, 0x3f000035, 0x0782149d,
337 0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
338 0x3f405458, 0x3f0fe424, 0x06924099,
339 0x3f607061, 0x3f1fd41d, 0x06024c97,
340 0x3f909068, 0x3f2fcc16, 0x05726490,
341 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
342 0x0000d077, 0x3f4fc409, 0x04627484 },
345 0x3f202040, 0x3f202040, 0x07a1e898,
346 0x3f303449, 0x3f100c38, 0x0741fc98,
347 0x3f504c50, 0x3f10002f, 0x06e21495,
348 0x3f706459, 0x3f1ff028, 0x06722492,
349 0x3fa08060, 0x3f1fe421, 0x05f2348f,
350 0x3fd09c67, 0x3f1fdc19, 0x05824c89,
351 0x0000bc6e, 0x3f2fd014, 0x04f25086,
352 0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
355 0x3f403042, 0x3f403042, 0x0761d890,
356 0x3f504848, 0x3f301c3b, 0x0701f090,
357 0x3f805c50, 0x3f200c33, 0x06a2008f,
358 0x3fa07458, 0x3f10002b, 0x06520c8d,
359 0x3fd0905e, 0x3f1ff424, 0x05e22089,
360 0x0000ac65, 0x3f1fe81d, 0x05823483,
361 0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
362 0x0080e871, 0x3f2fd412, 0x0482407c },
365 0x3f604043, 0x3f604043, 0x0721c88a,
366 0x3f80544a, 0x3f502c3c, 0x06d1d88a,
367 0x3fb06851, 0x3f301c35, 0x0681e889,
368 0x3fd08456, 0x3f30082f, 0x0611fc88,
369 0x00009c5d, 0x3f200027, 0x05d20884,
370 0x0030b863, 0x3f2ff421, 0x05621880,
371 0x0070d468, 0x3f2fe81b, 0x0502247c,
372 0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
375 0x3f904c44, 0x3f904c44, 0x06e1b884,
376 0x3fb0604a, 0x3f70383e, 0x0691c885,
377 0x3fe07451, 0x3f502c36, 0x0661d483,
378 0x00009055, 0x3f401831, 0x0601ec81,
379 0x0030a85b, 0x3f300c2a, 0x05b1f480,
380 0x0070c061, 0x3f300024, 0x0562047a,
381 0x00b0d867, 0x3f3ff41e, 0x05020c77,
382 0x00f0f46b, 0x3f2fec19, 0x04a21474 },
385 0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
386 0x3fe06c4b, 0x3f902c3f, 0x0681c081,
387 0x0000844f, 0x3f703838, 0x0631cc7d,
388 0x00309855, 0x3f602433, 0x05d1d47e,
389 0x0060b459, 0x3f50142e, 0x0581e47b,
390 0x00a0c85f, 0x3f400828, 0x0531f078,
391 0x00e0e064, 0x3f300021, 0x0501fc73,
392 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
395 0x3fe06444, 0x3fe06444, 0x0681a07a,
396 0x00007849, 0x3fc0503f, 0x0641b07a,
397 0x0020904d, 0x3fa0403a, 0x05f1c07a,
398 0x0060a453, 0x3f803034, 0x05c1c878,
399 0x0090b858, 0x3f70202f, 0x0571d477,
400 0x00d0d05d, 0x3f501829, 0x0531e073,
401 0x0110e462, 0x3f500825, 0x04e1e471,
402 0x01510065, 0x3f40001f, 0x04a1f06d },
405 0x00007044, 0x00007044, 0x06519476,
406 0x00208448, 0x3fe05c3f, 0x0621a476,
407 0x0050984d, 0x3fc04c3a, 0x05e1b075,
408 0x0080ac52, 0x3fa03c35, 0x05a1b875,
409 0x00c0c056, 0x3f803030, 0x0561c473,
410 0x0100d45b, 0x3f70202b, 0x0521d46f,
411 0x0140e860, 0x3f601427, 0x04d1d46e,
412 0x01810064, 0x3f500822, 0x0491dc6b },
415 0x0110a442, 0x0110a442, 0x0551545e,
416 0x0140b045, 0x00e0983f, 0x0531585f,
417 0x0160c047, 0x00c08c3c, 0x0511645e,
418 0x0190cc4a, 0x00908039, 0x04f1685f,
419 0x01c0dc4c, 0x00707436, 0x04d1705e,
420 0x0200e850, 0x00506833, 0x04b1785b,
421 0x0230f453, 0x00305c30, 0x0491805a,
422 0x02710056, 0x0010542d, 0x04718059 },
425 0x01c0bc40, 0x01c0bc40, 0x04c13052,
426 0x01e0c841, 0x01a0b43d, 0x04c13851,
427 0x0210cc44, 0x0180a83c, 0x04a13453,
428 0x0230d845, 0x0160a03a, 0x04913c52,
429 0x0260e047, 0x01409838, 0x04714052,
430 0x0280ec49, 0x01208c37, 0x04514c50,
431 0x02b0f44b, 0x01008435, 0x04414c50,
432 0x02d1004c, 0x00e07c33, 0x0431544f },
435 0x0230c83e, 0x0230c83e, 0x04711c4c,
436 0x0250d03f, 0x0210c43c, 0x0471204b,
437 0x0270d840, 0x0200b83c, 0x0451244b,
438 0x0290dc42, 0x01e0b43a, 0x0441244c,
439 0x02b0e443, 0x01c0b038, 0x0441284b,
440 0x02d0ec44, 0x01b0a438, 0x0421304a,
441 0x02f0f445, 0x0190a036, 0x04213449,
442 0x0310f847, 0x01709c34, 0x04213848 },
445 0x0280d03d, 0x0280d03d, 0x04310c48,
446 0x02a0d43e, 0x0270c83c, 0x04311047,
447 0x02b0dc3e, 0x0250c83a, 0x04311447,
448 0x02d0e040, 0x0240c03a, 0x04211446,
449 0x02e0e840, 0x0220bc39, 0x04111847,
450 0x0300e842, 0x0210b438, 0x04012445,
451 0x0310f043, 0x0200b037, 0x04012045,
452 0x0330f444, 0x01e0ac36, 0x03f12445 },
455 0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
456 0x0340e03a, 0x0330e039, 0x03c0f03e,
457 0x0350e03b, 0x0330dc39, 0x03c0ec3e,
458 0x0350e43a, 0x0320dc38, 0x03c0f43e,
459 0x0360e43b, 0x0320d839, 0x03b0f03e,
460 0x0360e83b, 0x0310d838, 0x03c0fc3b,
461 0x0370e83b, 0x0310d439, 0x03a0f83d,
462 0x0370e83c, 0x0300d438, 0x03b0fc3c },
466 enum rcar_vin_state {
472 struct rcar_vin_priv {
476 /* State of the VIN module in capturing mode */
477 enum rcar_vin_state state;
478 struct soc_camera_host ici;
479 struct list_head capture;
480 #define MAX_BUFFER_NUM 3
481 struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM];
482 struct vb2_alloc_ctx *alloc_ctx;
483 enum v4l2_field field;
484 unsigned int pdata_flags;
485 unsigned int vb_count;
486 unsigned int nr_hw_slots;
487 bool request_to_stop;
488 struct completion capture_stop;
492 #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
494 struct rcar_vin_buffer {
495 struct vb2_v4l2_buffer vb;
496 struct list_head list;
499 #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
500 struct rcar_vin_buffer, \
503 struct rcar_vin_cam {
504 /* VIN offsets within the camera output, before the VIN scaler */
505 unsigned int vin_left;
506 unsigned int vin_top;
507 /* Client output, as seen by the VIN */
510 /* User window from S_FMT */
511 unsigned int out_width;
512 unsigned int out_height;
514 * User window from S_CROP / G_CROP, produced by client cropping and
515 * scaling, VIN scaling and VIN cropping, mapped back onto the client
518 struct v4l2_rect subrect;
519 /* Camera cropping rectangle */
520 struct v4l2_rect rect;
521 const struct soc_mbus_pixelfmt *extra_fmt;
525 * .queue_setup() is called to check whether the driver can accept the requested
526 * number of buffers and to fill in plane sizes for the current frame format if
529 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
530 const struct v4l2_format *fmt,
532 unsigned int *num_planes,
533 unsigned int sizes[], void *alloc_ctxs[])
535 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
536 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
537 struct rcar_vin_priv *priv = ici->priv;
540 const struct soc_camera_format_xlate *xlate;
541 unsigned int bytes_per_line;
544 if (fmt->fmt.pix.sizeimage < icd->sizeimage)
547 xlate = soc_camera_xlate_by_fourcc(icd,
548 fmt->fmt.pix.pixelformat);
551 ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
556 bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret);
558 ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line,
559 fmt->fmt.pix.height);
563 sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret);
565 /* Called from VIDIOC_REQBUFS or in compatibility mode */
566 sizes[0] = icd->sizeimage;
569 alloc_ctxs[0] = priv->alloc_ctx;
571 if (!vq->num_buffers)
576 priv->vb_count = *count;
580 /* Number of hardware slots */
581 if (is_continuous_transfer(priv))
582 priv->nr_hw_slots = MAX_BUFFER_NUM;
584 priv->nr_hw_slots = 1;
586 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
591 static int rcar_vin_setup(struct rcar_vin_priv *priv)
593 struct soc_camera_device *icd = priv->ici.icd;
594 struct rcar_vin_cam *cam = icd->host_priv;
595 u32 vnmc, dmr, interrupts;
596 bool progressive = false, output_is_yuv = false, input_is_yuv = false;
598 switch (priv->field) {
602 case V4L2_FIELD_BOTTOM:
605 case V4L2_FIELD_INTERLACED:
606 case V4L2_FIELD_INTERLACED_TB:
609 case V4L2_FIELD_INTERLACED_BT:
610 vnmc = VNMC_IM_FULL | VNMC_FOC;
612 case V4L2_FIELD_NONE:
613 if (is_continuous_transfer(priv)) {
614 vnmc = VNMC_IM_ODD_EVEN;
625 /* input interface */
626 switch (icd->current_fmt->code) {
627 case MEDIA_BUS_FMT_YUYV8_1X16:
628 /* BT.601/BT.1358 16bit YCbCr422 */
629 vnmc |= VNMC_INF_YUV16;
632 case MEDIA_BUS_FMT_YUYV8_2X8:
633 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
634 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
635 VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
638 case MEDIA_BUS_FMT_RGB888_1X24:
639 vnmc |= VNMC_INF_RGB888;
641 case MEDIA_BUS_FMT_YUYV10_2X10:
642 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
643 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
644 VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
652 switch (icd->current_fmt->host_fmt->fourcc) {
653 case V4L2_PIX_FMT_NV16:
654 iowrite32(ALIGN(cam->width * cam->height, 0x80),
655 priv->base + VNUVAOF_REG);
656 dmr = VNDMR_DTMD_YCSEP;
657 output_is_yuv = true;
659 case V4L2_PIX_FMT_YUYV:
661 output_is_yuv = true;
663 case V4L2_PIX_FMT_UYVY:
665 output_is_yuv = true;
667 case V4L2_PIX_FMT_RGB555X:
668 dmr = VNDMR_DTMD_ARGB1555;
670 case V4L2_PIX_FMT_RGB565:
673 case V4L2_PIX_FMT_RGB32:
674 if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 ||
675 priv->chip == RCAR_E1) {
680 dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
681 icd->current_fmt->host_fmt->fourcc);
685 /* Always update on field change */
688 /* If input and output use the same colorspace, use bypass mode */
689 if (input_is_yuv == output_is_yuv)
692 /* progressive or interlaced mode */
693 interrupts = progressive ? VNIE_FIE : VNIE_EFE;
696 iowrite32(interrupts, priv->base + VNINTS_REG);
697 /* enable interrupts */
698 iowrite32(interrupts, priv->base + VNIE_REG);
699 /* start capturing */
700 iowrite32(dmr, priv->base + VNDMR_REG);
701 iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
706 static void rcar_vin_capture(struct rcar_vin_priv *priv)
708 if (is_continuous_transfer(priv))
709 /* Continuous Frame Capture Mode */
710 iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
712 /* Single Frame Capture Mode */
713 iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
716 static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
718 priv->state = STOPPING;
720 /* set continuous & single transfer off */
721 iowrite32(0, priv->base + VNFC_REG);
722 /* disable capture (release DMA buffer), reset */
723 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
724 priv->base + VNMC_REG);
726 /* update the status if stopped already */
727 if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
728 priv->state = STOPPED;
731 static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
735 for (slot = 0; slot < priv->nr_hw_slots; slot++)
736 if (priv->queue_buf[slot] == NULL)
742 static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
744 /* Ensure all HW slots are filled */
745 return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
748 /* Moves a buffer from the queue to the HW slots */
749 static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
751 struct vb2_v4l2_buffer *vbuf;
752 dma_addr_t phys_addr_top;
755 if (list_empty(&priv->capture))
758 /* Find a free HW slot */
759 slot = rcar_vin_get_free_hw_slot(priv);
763 vbuf = &list_entry(priv->capture.next,
764 struct rcar_vin_buffer, list)->vb;
765 list_del_init(to_buf_list(vbuf));
766 priv->queue_buf[slot] = vbuf;
767 phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
768 iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
773 static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
775 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
776 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
777 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
778 struct rcar_vin_priv *priv = ici->priv;
781 size = icd->sizeimage;
783 if (vb2_plane_size(vb, 0) < size) {
784 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
785 vb->index, vb2_plane_size(vb, 0), size);
789 vb2_set_plane_payload(vb, 0, size);
791 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
792 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
794 spin_lock_irq(&priv->lock);
796 list_add_tail(to_buf_list(vbuf), &priv->capture);
797 rcar_vin_fill_hw_slot(priv);
799 /* If we weren't running, and have enough buffers, start capturing! */
800 if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
801 if (rcar_vin_setup(priv)) {
803 list_del_init(to_buf_list(vbuf));
804 spin_unlock_irq(&priv->lock);
807 priv->request_to_stop = false;
808 init_completion(&priv->capture_stop);
809 priv->state = RUNNING;
810 rcar_vin_capture(priv);
813 spin_unlock_irq(&priv->lock);
818 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
822 * Wait for capture to stop and all in-flight buffers to be finished with by
823 * the video hardware. This must be called under &priv->lock
826 static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
828 while (priv->state != STOPPED) {
829 /* issue stop if running */
830 if (priv->state == RUNNING)
831 rcar_vin_request_capture_stop(priv);
833 /* wait until capturing has been stopped */
834 if (priv->state == STOPPING) {
835 priv->request_to_stop = true;
836 spin_unlock_irq(&priv->lock);
837 if (!wait_for_completion_timeout(
839 msecs_to_jiffies(TIMEOUT_MS)))
840 priv->state = STOPPED;
841 spin_lock_irq(&priv->lock);
846 static void rcar_vin_stop_streaming(struct vb2_queue *vq)
848 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
849 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
850 struct rcar_vin_priv *priv = ici->priv;
851 struct list_head *buf_head, *tmp;
854 spin_lock_irq(&priv->lock);
855 rcar_vin_wait_stop_streaming(priv);
857 for (i = 0; i < MAX_BUFFER_NUM; i++) {
858 if (priv->queue_buf[i]) {
859 vb2_buffer_done(&priv->queue_buf[i]->vb2_buf,
860 VB2_BUF_STATE_ERROR);
861 priv->queue_buf[i] = NULL;
865 list_for_each_safe(buf_head, tmp, &priv->capture) {
866 vb2_buffer_done(&list_entry(buf_head,
867 struct rcar_vin_buffer, list)->vb.vb2_buf,
868 VB2_BUF_STATE_ERROR);
869 list_del_init(buf_head);
871 spin_unlock_irq(&priv->lock);
874 static struct vb2_ops rcar_vin_vb2_ops = {
875 .queue_setup = rcar_vin_videobuf_setup,
876 .buf_queue = rcar_vin_videobuf_queue,
877 .stop_streaming = rcar_vin_stop_streaming,
878 .wait_prepare = vb2_ops_wait_prepare,
879 .wait_finish = vb2_ops_wait_finish,
882 static irqreturn_t rcar_vin_irq(int irq, void *data)
884 struct rcar_vin_priv *priv = data;
886 bool can_run = false, hw_stopped;
888 unsigned int handled = 0;
890 spin_lock(&priv->lock);
892 int_status = ioread32(priv->base + VNINTS_REG);
896 iowrite32(int_status, priv->base + VNINTS_REG);
899 /* nothing to do if capture status is 'STOPPED' */
900 if (priv->state == STOPPED)
903 hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
905 if (!priv->request_to_stop) {
906 if (is_continuous_transfer(priv))
907 slot = (ioread32(priv->base + VNMS_REG) &
908 VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
912 priv->queue_buf[slot]->field = priv->field;
913 priv->queue_buf[slot]->sequence = priv->sequence++;
914 v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp);
915 vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
917 priv->queue_buf[slot] = NULL;
919 if (priv->state != STOPPING)
920 can_run = rcar_vin_fill_hw_slot(priv);
922 if (hw_stopped || !can_run) {
923 priv->state = STOPPED;
924 } else if (is_continuous_transfer(priv) &&
925 list_empty(&priv->capture) &&
926 priv->state == RUNNING) {
928 * The continuous capturing requires an explicit stop
929 * operation when there is no buffer to be set into
930 * the VnMBm registers.
932 rcar_vin_request_capture_stop(priv);
934 rcar_vin_capture(priv);
937 } else if (hw_stopped) {
938 priv->state = STOPPED;
939 priv->request_to_stop = false;
940 complete(&priv->capture_stop);
944 spin_unlock(&priv->lock);
946 return IRQ_RETVAL(handled);
949 static int rcar_vin_add_device(struct soc_camera_device *icd)
951 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
952 struct rcar_vin_priv *priv = ici->priv;
955 for (i = 0; i < MAX_BUFFER_NUM; i++)
956 priv->queue_buf[i] = NULL;
958 pm_runtime_get_sync(ici->v4l2_dev.dev);
960 dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
966 static void rcar_vin_remove_device(struct soc_camera_device *icd)
968 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
969 struct rcar_vin_priv *priv = ici->priv;
970 struct vb2_v4l2_buffer *vbuf;
973 /* disable capture, disable interrupts */
974 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
975 priv->base + VNMC_REG);
976 iowrite32(0, priv->base + VNIE_REG);
978 priv->state = STOPPED;
979 priv->request_to_stop = false;
981 /* make sure active buffer is cancelled */
982 spin_lock_irq(&priv->lock);
983 for (i = 0; i < MAX_BUFFER_NUM; i++) {
984 vbuf = priv->queue_buf[i];
986 list_del_init(to_buf_list(vbuf));
987 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
990 spin_unlock_irq(&priv->lock);
992 pm_runtime_put(ici->v4l2_dev.dev);
994 dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
998 static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
1001 const struct vin_coeff *p_prev_set = NULL;
1002 const struct vin_coeff *p_set = NULL;
1004 /* Look for suitable coefficient values */
1005 for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
1007 p_set = &vin_coeff_set[i];
1009 if (xs < p_set->xs_value)
1013 /* Use previous value if its XS value is closer */
1014 if (p_prev_set && p_set &&
1015 xs - p_prev_set->xs_value < p_set->xs_value - xs)
1018 /* Set coefficient registers */
1019 iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
1020 iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
1021 iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
1023 iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
1024 iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
1025 iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
1027 iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
1028 iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
1029 iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
1031 iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
1032 iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
1033 iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
1035 iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
1036 iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
1037 iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
1039 iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
1040 iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
1041 iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
1043 iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
1044 iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
1045 iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
1047 iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
1048 iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
1049 iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
1052 /* rect is guaranteed to not exceed the scaled camera rectangle */
1053 static int rcar_vin_set_rect(struct soc_camera_device *icd)
1055 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1056 struct rcar_vin_cam *cam = icd->host_priv;
1057 struct rcar_vin_priv *priv = ici->priv;
1058 unsigned int left_offset, top_offset;
1059 unsigned char dsize = 0;
1060 struct v4l2_rect *cam_subrect = &cam->subrect;
1063 dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
1064 icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
1066 left_offset = cam->vin_left;
1067 top_offset = cam->vin_top;
1069 if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 &&
1070 priv->chip == RCAR_E1)
1073 dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
1074 cam->width, cam->height, cam->vin_left, cam->vin_top);
1075 dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
1076 cam_subrect->width, cam_subrect->height,
1077 cam_subrect->left, cam_subrect->top);
1079 /* Set Start/End Pixel/Line Pre-Clip */
1080 iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
1081 iowrite32((left_offset + cam_subrect->width - 1) << dsize,
1082 priv->base + VNEPPRC_REG);
1083 switch (priv->field) {
1084 case V4L2_FIELD_INTERLACED:
1085 case V4L2_FIELD_INTERLACED_TB:
1086 case V4L2_FIELD_INTERLACED_BT:
1087 iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
1088 iowrite32((top_offset + cam_subrect->height) / 2 - 1,
1089 priv->base + VNELPRC_REG);
1092 iowrite32(top_offset, priv->base + VNSLPRC_REG);
1093 iowrite32(top_offset + cam_subrect->height - 1,
1094 priv->base + VNELPRC_REG);
1098 /* Set scaling coefficient */
1100 if (cam_subrect->height != cam->out_height)
1101 value = (4096 * cam_subrect->height) / cam->out_height;
1102 dev_dbg(icd->parent, "YS Value: %x\n", value);
1103 iowrite32(value, priv->base + VNYS_REG);
1106 if (cam_subrect->width != cam->out_width)
1107 value = (4096 * cam_subrect->width) / cam->out_width;
1109 /* Horizontal upscaling is up to double size */
1110 if (0 < value && value < 2048)
1113 dev_dbg(icd->parent, "XS Value: %x\n", value);
1114 iowrite32(value, priv->base + VNXS_REG);
1116 /* Horizontal upscaling is carried out by scaling down from double size */
1120 set_coeff(priv, value);
1122 /* Set Start/End Pixel/Line Post-Clip */
1123 iowrite32(0, priv->base + VNSPPOC_REG);
1124 iowrite32(0, priv->base + VNSLPOC_REG);
1125 iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
1126 switch (priv->field) {
1127 case V4L2_FIELD_INTERLACED:
1128 case V4L2_FIELD_INTERLACED_TB:
1129 case V4L2_FIELD_INTERLACED_BT:
1130 iowrite32(cam->out_height / 2 - 1,
1131 priv->base + VNELPOC_REG);
1134 iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
1138 iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
1143 static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
1145 *vnmc = ioread32(priv->base + VNMC_REG);
1146 /* module disable */
1147 iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
1150 static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
1152 unsigned long timeout = jiffies + 10 * HZ;
1155 * Wait until the end of the current frame. It can take a long time,
1156 * but if it has been aborted by a MRST1 reset, it should exit sooner.
1158 while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
1159 time_before(jiffies, timeout))
1162 if (time_after(jiffies, timeout)) {
1163 dev_err(priv->ici.v4l2_dev.dev,
1164 "Timeout waiting for frame end! Interface problem?\n");
1168 iowrite32(vnmc, priv->base + VNMC_REG);
1171 #define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \
1172 V4L2_MBUS_PCLK_SAMPLE_RISING | \
1173 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
1174 V4L2_MBUS_HSYNC_ACTIVE_LOW | \
1175 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
1176 V4L2_MBUS_VSYNC_ACTIVE_LOW | \
1177 V4L2_MBUS_DATA_ACTIVE_HIGH)
1179 static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
1181 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1182 struct rcar_vin_priv *priv = ici->priv;
1183 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1184 struct v4l2_mbus_config cfg;
1185 unsigned long common_flags;
1190 capture_stop_preserve(priv, &vnmc);
1192 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1194 common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1195 if (!common_flags) {
1196 dev_warn(icd->parent,
1197 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1198 cfg.flags, VIN_MBUS_FLAGS);
1201 } else if (ret != -ENOIOCTLCMD) {
1204 common_flags = VIN_MBUS_FLAGS;
1207 /* Make choises, based on platform preferences */
1208 if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1209 (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
1210 if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
1211 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1213 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1216 if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1217 (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
1218 if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
1219 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1221 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1224 cfg.flags = common_flags;
1225 ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1226 if (ret < 0 && ret != -ENOIOCTLCMD)
1229 val = VNDMR2_FTEV | VNDMR2_VLV(1);
1230 if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
1232 if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
1234 iowrite32(val, priv->base + VNDMR2_REG);
1236 ret = rcar_vin_set_rect(icd);
1240 capture_restore(priv, vnmc);
1245 static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
1246 unsigned char buswidth)
1248 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1249 struct v4l2_mbus_config cfg;
1252 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1253 if (ret == -ENOIOCTLCMD)
1261 /* check is there common mbus flags */
1262 ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1266 dev_warn(icd->parent,
1267 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1268 cfg.flags, VIN_MBUS_FLAGS);
1273 static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1275 return fmt->packing == SOC_MBUS_PACKING_NONE ||
1276 (fmt->bits_per_sample > 8 &&
1277 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1280 static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
1282 .fourcc = V4L2_PIX_FMT_NV16,
1284 .bits_per_sample = 8,
1285 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1286 .order = SOC_MBUS_ORDER_LE,
1287 .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
1290 .fourcc = V4L2_PIX_FMT_YUYV,
1292 .bits_per_sample = 16,
1293 .packing = SOC_MBUS_PACKING_NONE,
1294 .order = SOC_MBUS_ORDER_LE,
1295 .layout = SOC_MBUS_LAYOUT_PACKED,
1298 .fourcc = V4L2_PIX_FMT_UYVY,
1300 .bits_per_sample = 16,
1301 .packing = SOC_MBUS_PACKING_NONE,
1302 .order = SOC_MBUS_ORDER_LE,
1303 .layout = SOC_MBUS_LAYOUT_PACKED,
1306 .fourcc = V4L2_PIX_FMT_RGB565,
1308 .bits_per_sample = 16,
1309 .packing = SOC_MBUS_PACKING_NONE,
1310 .order = SOC_MBUS_ORDER_LE,
1311 .layout = SOC_MBUS_LAYOUT_PACKED,
1314 .fourcc = V4L2_PIX_FMT_RGB555X,
1316 .bits_per_sample = 16,
1317 .packing = SOC_MBUS_PACKING_NONE,
1318 .order = SOC_MBUS_ORDER_LE,
1319 .layout = SOC_MBUS_LAYOUT_PACKED,
1322 .fourcc = V4L2_PIX_FMT_RGB32,
1324 .bits_per_sample = 32,
1325 .packing = SOC_MBUS_PACKING_NONE,
1326 .order = SOC_MBUS_ORDER_LE,
1327 .layout = SOC_MBUS_LAYOUT_PACKED,
1331 static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
1332 struct soc_camera_format_xlate *xlate)
1334 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1335 struct device *dev = icd->parent;
1338 struct rcar_vin_cam *cam;
1339 struct v4l2_subdev_mbus_code_enum code = {
1340 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1343 const struct soc_mbus_pixelfmt *fmt;
1345 ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
1349 fmt = soc_mbus_get_fmtdesc(code.code);
1351 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
1355 ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1359 if (!icd->host_priv) {
1360 struct v4l2_subdev_format fmt = {
1361 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1363 struct v4l2_mbus_framefmt *mf = &fmt.format;
1364 struct v4l2_rect rect;
1365 struct device *dev = icd->parent;
1368 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1372 /* Cache current client geometry */
1373 ret = soc_camera_client_g_rect(sd, &rect);
1374 if (ret == -ENOIOCTLCMD) {
1375 /* Sensor driver doesn't support cropping */
1378 rect.width = mf->width;
1379 rect.height = mf->height;
1380 } else if (ret < 0) {
1385 * If sensor proposes too large format then try smaller ones:
1386 * 1280x960, 640x480, 320x240
1388 for (shift = 0; shift < 3; shift++) {
1389 if (mf->width <= VIN_MAX_WIDTH &&
1390 mf->height <= VIN_MAX_HEIGHT)
1393 mf->width = 1280 >> shift;
1394 mf->height = 960 >> shift;
1395 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1396 soc_camera_grp_id(icd),
1405 "Failed to configure the client below %ux%u\n",
1406 mf->width, mf->height);
1410 dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
1412 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1416 * We are called with current camera crop,
1417 * initialise subrect with it
1420 cam->subrect = rect;
1421 cam->width = mf->width;
1422 cam->height = mf->height;
1423 cam->out_width = mf->width;
1424 cam->out_height = mf->height;
1426 icd->host_priv = cam;
1428 cam = icd->host_priv;
1431 /* Beginning of a pass */
1433 cam->extra_fmt = NULL;
1435 switch (code.code) {
1436 case MEDIA_BUS_FMT_YUYV8_1X16:
1437 case MEDIA_BUS_FMT_YUYV8_2X8:
1438 case MEDIA_BUS_FMT_YUYV10_2X10:
1439 case MEDIA_BUS_FMT_RGB888_1X24:
1443 /* Add all our formats that can be generated by VIN */
1444 cam->extra_fmt = rcar_vin_formats;
1446 n = ARRAY_SIZE(rcar_vin_formats);
1448 for (k = 0; xlate && k < n; k++, xlate++) {
1449 xlate->host_fmt = &rcar_vin_formats[k];
1450 xlate->code = code.code;
1451 dev_dbg(dev, "Providing format %s using code %d\n",
1452 rcar_vin_formats[k].name, code.code);
1456 if (!rcar_vin_packing_supported(fmt))
1459 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1464 /* Generic pass-through */
1467 xlate->host_fmt = fmt;
1468 xlate->code = code.code;
1475 static void rcar_vin_put_formats(struct soc_camera_device *icd)
1477 kfree(icd->host_priv);
1478 icd->host_priv = NULL;
1481 static int rcar_vin_set_crop(struct soc_camera_device *icd,
1482 const struct v4l2_crop *a)
1484 struct v4l2_crop a_writable = *a;
1485 const struct v4l2_rect *rect = &a_writable.c;
1486 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1487 struct rcar_vin_priv *priv = ici->priv;
1488 struct v4l2_crop cam_crop;
1489 struct rcar_vin_cam *cam = icd->host_priv;
1490 struct v4l2_rect *cam_rect = &cam_crop.c;
1491 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1492 struct device *dev = icd->parent;
1493 struct v4l2_subdev_format fmt = {
1494 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1496 struct v4l2_mbus_framefmt *mf = &fmt.format;
1500 dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
1501 rect->left, rect->top);
1503 /* During camera cropping its output window can change too, stop VIN */
1504 capture_stop_preserve(priv, &vnmc);
1505 dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1507 /* Apply iterative camera S_CROP for new input window. */
1508 ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
1509 &cam->rect, &cam->subrect);
1513 dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
1514 cam_rect->width, cam_rect->height,
1515 cam_rect->left, cam_rect->top);
1517 /* On success cam_crop contains current camera crop */
1519 /* Retrieve camera output window */
1520 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1524 if (mf->width > VIN_MAX_WIDTH || mf->height > VIN_MAX_HEIGHT)
1527 /* Cache camera output window */
1528 cam->width = mf->width;
1529 cam->height = mf->height;
1531 icd->user_width = cam->width;
1532 icd->user_height = cam->height;
1534 cam->vin_left = rect->left & ~1;
1535 cam->vin_top = rect->top & ~1;
1537 /* Use VIN cropping to crop to the new window. */
1538 ret = rcar_vin_set_rect(icd);
1542 cam->subrect = *rect;
1544 dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
1545 icd->user_width, icd->user_height,
1546 cam->vin_left, cam->vin_top);
1548 /* Restore capture */
1549 for (i = 0; i < MAX_BUFFER_NUM; i++) {
1550 if (priv->queue_buf[i] && priv->state == STOPPED) {
1555 capture_restore(priv, vnmc);
1557 /* Even if only camera cropping succeeded */
1561 static int rcar_vin_get_crop(struct soc_camera_device *icd,
1562 struct v4l2_crop *a)
1564 struct rcar_vin_cam *cam = icd->host_priv;
1566 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1567 a->c = cam->subrect;
1572 /* Similar to set_crop multistage iterative algorithm */
1573 static int rcar_vin_set_fmt(struct soc_camera_device *icd,
1574 struct v4l2_format *f)
1576 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1577 struct rcar_vin_priv *priv = ici->priv;
1578 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1579 struct rcar_vin_cam *cam = icd->host_priv;
1580 struct v4l2_pix_format *pix = &f->fmt.pix;
1581 struct v4l2_mbus_framefmt mf;
1582 struct device *dev = icd->parent;
1583 __u32 pixfmt = pix->pixelformat;
1584 const struct soc_camera_format_xlate *xlate;
1585 unsigned int vin_sub_width = 0, vin_sub_height = 0;
1588 enum v4l2_field field;
1591 dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
1592 pixfmt, pix->width, pix->height);
1594 switch (pix->field) {
1596 pix->field = V4L2_FIELD_NONE;
1598 case V4L2_FIELD_NONE:
1599 case V4L2_FIELD_TOP:
1600 case V4L2_FIELD_BOTTOM:
1601 case V4L2_FIELD_INTERLACED_TB:
1602 case V4L2_FIELD_INTERLACED_BT:
1605 case V4L2_FIELD_INTERLACED:
1606 /* Get the last standard if not explicitly mentioned _TB/_BT */
1607 ret = v4l2_subdev_call(sd, video, g_std, &std);
1608 if (ret == -ENOIOCTLCMD) {
1609 field = V4L2_FIELD_NONE;
1610 } else if (ret < 0) {
1613 field = std & V4L2_STD_625_50 ?
1614 V4L2_FIELD_INTERLACED_TB :
1615 V4L2_FIELD_INTERLACED_BT;
1620 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1622 dev_warn(dev, "Format %x not found\n", pixfmt);
1625 /* Calculate client output geometry */
1626 soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1628 mf.field = pix->field;
1629 mf.colorspace = pix->colorspace;
1630 mf.code = xlate->code;
1633 case V4L2_PIX_FMT_RGB32:
1634 can_scale = priv->chip != RCAR_E1;
1636 case V4L2_PIX_FMT_UYVY:
1637 case V4L2_PIX_FMT_YUYV:
1638 case V4L2_PIX_FMT_RGB565:
1639 case V4L2_PIX_FMT_RGB555X:
1647 dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1649 ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1650 &mf, &vin_sub_width, &vin_sub_height,
1653 /* Done with the camera. Now see if we can improve the result */
1654 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1655 ret, mf.width, mf.height, pix->width, pix->height);
1657 if (ret == -ENOIOCTLCMD)
1658 dev_dbg(dev, "Sensor doesn't support scaling\n");
1662 if (mf.code != xlate->code)
1665 /* Prepare VIN crop */
1666 cam->width = mf.width;
1667 cam->height = mf.height;
1669 /* Use VIN scaling to scale to the requested user window. */
1671 /* We cannot scale up */
1672 if (pix->width > vin_sub_width)
1673 vin_sub_width = pix->width;
1675 if (pix->height > vin_sub_height)
1676 vin_sub_height = pix->height;
1678 pix->colorspace = mf.colorspace;
1681 pix->width = vin_sub_width;
1682 pix->height = vin_sub_height;
1686 * We have calculated CFLCR, the actual configuration will be performed
1687 * in rcar_vin_set_bus_param()
1690 dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1691 vin_sub_width, pix->width, vin_sub_height, pix->height);
1693 cam->out_width = pix->width;
1694 cam->out_height = pix->height;
1696 icd->current_fmt = xlate;
1698 priv->field = field;
1703 static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1704 struct v4l2_format *f)
1706 const struct soc_camera_format_xlate *xlate;
1707 struct v4l2_pix_format *pix = &f->fmt.pix;
1708 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1709 struct v4l2_subdev_pad_config pad_cfg;
1710 struct v4l2_subdev_format format = {
1711 .which = V4L2_SUBDEV_FORMAT_TRY,
1713 struct v4l2_mbus_framefmt *mf = &format.format;
1714 __u32 pixfmt = pix->pixelformat;
1718 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1720 xlate = icd->current_fmt;
1721 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1722 pixfmt, xlate->host_fmt->fourcc);
1723 pixfmt = xlate->host_fmt->fourcc;
1724 pix->pixelformat = pixfmt;
1725 pix->colorspace = icd->colorspace;
1728 /* FIXME: calculate using depth and bus width */
1729 v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1730 &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1733 height = pix->height;
1735 /* let soc-camera calculate these values */
1736 pix->bytesperline = 0;
1739 /* limit to sensor capabilities */
1740 mf->width = pix->width;
1741 mf->height = pix->height;
1742 mf->field = pix->field;
1743 mf->code = xlate->code;
1744 mf->colorspace = pix->colorspace;
1746 ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
1747 pad, set_fmt, &pad_cfg, &format);
1751 /* Adjust only if VIN cannot scale */
1752 if (pix->width > mf->width * 2)
1753 pix->width = mf->width * 2;
1754 if (pix->height > mf->height * 3)
1755 pix->height = mf->height * 3;
1757 pix->field = mf->field;
1758 pix->colorspace = mf->colorspace;
1760 if (pixfmt == V4L2_PIX_FMT_NV16) {
1761 /* FIXME: check against rect_max after converting soc-camera */
1762 /* We can scale precisely, need a bigger image from camera */
1763 if (pix->width < width || pix->height < height) {
1765 * We presume, the sensor behaves sanely, i.e. if
1766 * requested a bigger rectangle, it will not return a
1769 mf->width = VIN_MAX_WIDTH;
1770 mf->height = VIN_MAX_HEIGHT;
1771 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1772 soc_camera_grp_id(icd),
1773 pad, set_fmt, &pad_cfg,
1776 dev_err(icd->parent,
1777 "client try_fmt() = %d\n", ret);
1781 /* We will scale exactly */
1782 if (mf->width > width)
1784 if (mf->height > height)
1785 pix->height = height;
1791 static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1793 struct soc_camera_device *icd = file->private_data;
1795 return vb2_poll(&icd->vb2_vidq, file, pt);
1798 static int rcar_vin_querycap(struct soc_camera_host *ici,
1799 struct v4l2_capability *cap)
1801 strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
1802 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1803 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1804 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr);
1809 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1810 struct soc_camera_device *icd)
1812 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1814 vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1815 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1817 vq->ops = &rcar_vin_vb2_ops;
1818 vq->mem_ops = &vb2_dma_contig_memops;
1819 vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
1820 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1821 vq->lock = &ici->host_lock;
1823 return vb2_queue_init(vq);
1826 static struct soc_camera_host_ops rcar_vin_host_ops = {
1827 .owner = THIS_MODULE,
1828 .add = rcar_vin_add_device,
1829 .remove = rcar_vin_remove_device,
1830 .get_formats = rcar_vin_get_formats,
1831 .put_formats = rcar_vin_put_formats,
1832 .get_crop = rcar_vin_get_crop,
1833 .set_crop = rcar_vin_set_crop,
1834 .try_fmt = rcar_vin_try_fmt,
1835 .set_fmt = rcar_vin_set_fmt,
1836 .poll = rcar_vin_poll,
1837 .querycap = rcar_vin_querycap,
1838 .set_bus_param = rcar_vin_set_bus_param,
1839 .init_videobuf2 = rcar_vin_init_videobuf2,
1843 static const struct of_device_id rcar_vin_of_table[] = {
1844 { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1845 { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
1846 { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1847 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1848 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1849 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1852 MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1855 static struct platform_device_id rcar_vin_id_table[] = {
1856 { "r8a7779-vin", RCAR_H1 },
1857 { "r8a7778-vin", RCAR_M1 },
1858 { "uPD35004-vin", RCAR_E1 },
1861 MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
1863 static int rcar_vin_probe(struct platform_device *pdev)
1865 const struct of_device_id *match = NULL;
1866 struct rcar_vin_priv *priv;
1867 struct resource *mem;
1868 struct rcar_vin_platform_data *pdata;
1869 unsigned int pdata_flags;
1872 if (pdev->dev.of_node) {
1873 struct v4l2_of_endpoint ep;
1874 struct device_node *np;
1876 match = of_match_device(of_match_ptr(rcar_vin_of_table),
1879 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1881 dev_err(&pdev->dev, "could not find endpoint\n");
1885 ret = v4l2_of_parse_endpoint(np, &ep);
1887 dev_err(&pdev->dev, "could not parse endpoint\n");
1891 if (ep.bus_type == V4L2_MBUS_BT656)
1892 pdata_flags = RCAR_VIN_BT656;
1895 if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1896 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1897 if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1898 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1903 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1905 pdata = pdev->dev.platform_data;
1906 if (!pdata || !pdata->flags) {
1907 dev_err(&pdev->dev, "platform data not set\n");
1910 pdata_flags = pdata->flags;
1913 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1917 irq = platform_get_irq(pdev, 0);
1921 priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1926 priv->base = devm_ioremap_resource(&pdev->dev, mem);
1927 if (IS_ERR(priv->base))
1928 return PTR_ERR(priv->base);
1930 ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1931 dev_name(&pdev->dev), priv);
1935 priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1936 if (IS_ERR(priv->alloc_ctx))
1937 return PTR_ERR(priv->alloc_ctx);
1939 priv->ici.priv = priv;
1940 priv->ici.v4l2_dev.dev = &pdev->dev;
1941 priv->ici.drv_name = dev_name(&pdev->dev);
1942 priv->ici.ops = &rcar_vin_host_ops;
1944 priv->pdata_flags = pdata_flags;
1946 priv->ici.nr = pdev->id;
1947 priv->chip = pdev->id_entry->driver_data;
1949 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1950 priv->chip = (enum chip_id)match->data;
1953 spin_lock_init(&priv->lock);
1954 INIT_LIST_HEAD(&priv->capture);
1956 priv->state = STOPPED;
1958 pm_suspend_ignore_children(&pdev->dev, true);
1959 pm_runtime_enable(&pdev->dev);
1961 ret = soc_camera_host_register(&priv->ici);
1968 pm_runtime_disable(&pdev->dev);
1969 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1974 static int rcar_vin_remove(struct platform_device *pdev)
1976 struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1977 struct rcar_vin_priv *priv = container_of(soc_host,
1978 struct rcar_vin_priv, ici);
1980 soc_camera_host_unregister(soc_host);
1981 pm_runtime_disable(&pdev->dev);
1982 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1987 static struct platform_driver rcar_vin_driver = {
1988 .probe = rcar_vin_probe,
1989 .remove = rcar_vin_remove,
1992 .of_match_table = of_match_ptr(rcar_vin_of_table),
1994 .id_table = rcar_vin_id_table,
1997 module_platform_driver(rcar_vin_driver);
1999 MODULE_LICENSE("GPL");
2000 MODULE_ALIAS("platform:rcar_vin");
2001 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");