[media] include/media: move driver interface headers to a separate dir
[deliverable/linux.git] / drivers / media / platform / soc_camera / rcar_vin.c
CommitLineData
73135e96
VB
1/*
2 * SoC-camera host driver for Renesas R-Car VIN unit
3 *
4 * Copyright (C) 2011-2013 Renesas Solutions Corp.
5 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
6 *
7 * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c"
8 *
9 * Copyright (C) 2008 Magnus Damm
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/delay.h>
18#include <linux/interrupt.h>
3cdcf736 19#include <linux/io.h>
73135e96
VB
20#include <linux/kernel.h>
21#include <linux/module.h>
47c71bd6
BD
22#include <linux/of.h>
23#include <linux/of_device.h>
73135e96
VB
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>
29
30#include <media/soc_camera.h>
d647f0b7 31#include <media/drv-intf/soc_mediabus.h>
73135e96
VB
32#include <media/v4l2-common.h>
33#include <media/v4l2-dev.h>
34#include <media/v4l2-device.h>
35#include <media/v4l2-mediabus.h>
47c71bd6 36#include <media/v4l2-of.h>
73135e96
VB
37#include <media/v4l2-subdev.h>
38#include <media/videobuf2-dma-contig.h>
39
40#include "soc_scale_crop.h"
41
42#define DRV_NAME "rcar_vin"
43
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 */
4c28078c
KM
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 */
73135e96
VB
91
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)
cbe504d4
PE
98#define VNMC_INF_YUV10_BT656 (2 << 16)
99#define VNMC_INF_YUV10_BT601 (3 << 16)
73135e96 100#define VNMC_INF_YUV16 (5 << 16)
920a1bf3 101#define VNMC_INF_RGB888 (6 << 16)
73135e96
VB
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)
109
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)
115
116/* Video n Frame Capture Register bits */
117#define VNFC_C_FRAME (1 << 1)
118#define VNFC_S_FRAME (1 << 0)
119
120/* Video n Interrupt Enable Register bits */
121#define VNIE_FIE (1 << 4)
122#define VNIE_EFE (1 << 1)
123
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)
129
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)
609f33c9 134#define VNDMR2_VLV(n) ((n & 0xf) << 12)
73135e96
VB
135
136#define VIN_MAX_WIDTH 2048
137#define VIN_MAX_HEIGHT 2048
138
5a9b06a2
KM
139#define TIMEOUT_MS 100
140
73135e96 141enum chip_id {
2a9ecc17 142 RCAR_GEN2,
73135e96
VB
143 RCAR_H1,
144 RCAR_M1,
145 RCAR_E1,
146};
147
4c28078c
KM
148struct vin_coeff {
149 unsigned short xs_value;
150 u32 coeff_set[24];
151};
152
153static const struct vin_coeff vin_coeff_set[] = {
154 { 0x0000, {
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 },
163 },
164 { 0x1000, {
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 },
173 },
174 { 0x1200, {
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 },
183 },
184 { 0x1400, {
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 },
193 },
194 { 0x1600, {
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 },
203 },
204 { 0x1800, {
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 },
213 },
214 { 0x1a00, {
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 },
223 },
224 { 0x1c00, {
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 },
233 },
234 { 0x1e00, {
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 },
243 },
244 { 0x2000, {
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 },
253 },
254 { 0x2200, {
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 },
263 },
264 { 0x2400, {
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 },
273 },
274 { 0x2600, {
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 },
283 },
284 { 0x2800, {
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 },
293 },
294 { 0x2a00, {
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 },
303 },
304 { 0x2c00, {
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 },
313 },
314 { 0x2e00, {
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 },
323 },
324 { 0x3000, {
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 },
333 },
334 { 0x3200, {
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 },
343 },
344 { 0x3400, {
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 },
353 },
354 { 0x3600, {
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 },
363 },
364 { 0x3800, {
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 },
373 },
374 { 0x3a00, {
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 },
383 },
384 { 0x3c00, {
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 },
393 },
394 { 0x3e00, {
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 },
403 },
404 { 0x4000, {
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 },
413 },
414 { 0x5000, {
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 },
423 },
424 { 0x6000, {
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 },
433 },
434 { 0x7000, {
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 },
443 },
444 { 0x8000, {
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 },
453 },
454 { 0xefff, {
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 },
463 }
464};
465
73135e96
VB
466enum rcar_vin_state {
467 STOPPED = 0,
468 RUNNING,
469 STOPPING,
470};
471
472struct rcar_vin_priv {
473 void __iomem *base;
474 spinlock_t lock;
475 int sequence;
476 /* State of the VIN module in capturing mode */
477 enum rcar_vin_state state;
73135e96
VB
478 struct soc_camera_host ici;
479 struct list_head capture;
480#define MAX_BUFFER_NUM 3
2d700715 481 struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM];
73135e96
VB
482 struct vb2_alloc_ctx *alloc_ctx;
483 enum v4l2_field field;
25dfa02c 484 unsigned int pdata_flags;
73135e96
VB
485 unsigned int vb_count;
486 unsigned int nr_hw_slots;
487 bool request_to_stop;
488 struct completion capture_stop;
489 enum chip_id chip;
490};
491
492#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
493
494struct rcar_vin_buffer {
2d700715 495 struct vb2_v4l2_buffer vb;
73135e96
VB
496 struct list_head list;
497};
498
499#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
500 struct rcar_vin_buffer, \
501 vb)->list)
502
503struct 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 */
508 unsigned int width;
509 unsigned int height;
4c28078c
KM
510 /* User window from S_FMT */
511 unsigned int out_width;
512 unsigned int out_height;
73135e96
VB
513 /*
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
516 * input window
517 */
518 struct v4l2_rect subrect;
519 /* Camera cropping rectangle */
520 struct v4l2_rect rect;
521 const struct soc_mbus_pixelfmt *extra_fmt;
522};
523
524/*
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
527 * required
528 */
529static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
33119e80 530 const void *parg,
73135e96
VB
531 unsigned int *count,
532 unsigned int *num_planes,
533 unsigned int sizes[], void *alloc_ctxs[])
534{
33119e80 535 const struct v4l2_format *fmt = parg;
73135e96
VB
536 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
537 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
538 struct rcar_vin_priv *priv = ici->priv;
539
540 if (fmt) {
541 const struct soc_camera_format_xlate *xlate;
542 unsigned int bytes_per_line;
543 int ret;
544
42841180
RT
545 if (fmt->fmt.pix.sizeimage < icd->sizeimage)
546 return -EINVAL;
547
73135e96
VB
548 xlate = soc_camera_xlate_by_fourcc(icd,
549 fmt->fmt.pix.pixelformat);
550 if (!xlate)
551 return -EINVAL;
552 ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
553 xlate->host_fmt);
554 if (ret < 0)
555 return ret;
556
557 bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret);
558
559 ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line,
560 fmt->fmt.pix.height);
561 if (ret < 0)
562 return ret;
563
564 sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret);
565 } else {
566 /* Called from VIDIOC_REQBUFS or in compatibility mode */
567 sizes[0] = icd->sizeimage;
568 }
569
570 alloc_ctxs[0] = priv->alloc_ctx;
571
572 if (!vq->num_buffers)
573 priv->sequence = 0;
574
575 if (!*count)
576 *count = 2;
577 priv->vb_count = *count;
578
579 *num_planes = 1;
580
581 /* Number of hardware slots */
582 if (is_continuous_transfer(priv))
583 priv->nr_hw_slots = MAX_BUFFER_NUM;
584 else
585 priv->nr_hw_slots = 1;
586
587 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
588
589 return 0;
590}
591
592static int rcar_vin_setup(struct rcar_vin_priv *priv)
593{
594 struct soc_camera_device *icd = priv->ici.icd;
595 struct rcar_vin_cam *cam = icd->host_priv;
596 u32 vnmc, dmr, interrupts;
920a1bf3 597 bool progressive = false, output_is_yuv = false, input_is_yuv = false;
73135e96
VB
598
599 switch (priv->field) {
600 case V4L2_FIELD_TOP:
601 vnmc = VNMC_IM_ODD;
602 break;
603 case V4L2_FIELD_BOTTOM:
604 vnmc = VNMC_IM_EVEN;
605 break;
606 case V4L2_FIELD_INTERLACED:
607 case V4L2_FIELD_INTERLACED_TB:
608 vnmc = VNMC_IM_FULL;
609 break;
610 case V4L2_FIELD_INTERLACED_BT:
611 vnmc = VNMC_IM_FULL | VNMC_FOC;
612 break;
613 case V4L2_FIELD_NONE:
614 if (is_continuous_transfer(priv)) {
615 vnmc = VNMC_IM_ODD_EVEN;
616 progressive = true;
617 } else {
618 vnmc = VNMC_IM_ODD;
619 }
620 break;
621 default:
622 vnmc = VNMC_IM_ODD;
623 break;
624 }
625
626 /* input interface */
627 switch (icd->current_fmt->code) {
27ffaeb0 628 case MEDIA_BUS_FMT_YUYV8_1X16:
73135e96
VB
629 /* BT.601/BT.1358 16bit YCbCr422 */
630 vnmc |= VNMC_INF_YUV16;
920a1bf3 631 input_is_yuv = true;
73135e96 632 break;
27ffaeb0 633 case MEDIA_BUS_FMT_YUYV8_2X8:
73135e96 634 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
25dfa02c 635 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
73135e96 636 VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
920a1bf3
WT
637 input_is_yuv = true;
638 break;
639 case MEDIA_BUS_FMT_RGB888_1X24:
640 vnmc |= VNMC_INF_RGB888;
cbe504d4 641 break;
27ffaeb0 642 case MEDIA_BUS_FMT_YUYV10_2X10:
cbe504d4 643 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
25dfa02c 644 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
cbe504d4 645 VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
920a1bf3 646 input_is_yuv = true;
cbe504d4 647 break;
73135e96
VB
648 default:
649 break;
650 }
651
652 /* output format */
653 switch (icd->current_fmt->host_fmt->fourcc) {
654 case V4L2_PIX_FMT_NV16:
655 iowrite32(ALIGN(cam->width * cam->height, 0x80),
656 priv->base + VNUVAOF_REG);
657 dmr = VNDMR_DTMD_YCSEP;
658 output_is_yuv = true;
659 break;
660 case V4L2_PIX_FMT_YUYV:
661 dmr = VNDMR_BPSM;
662 output_is_yuv = true;
663 break;
664 case V4L2_PIX_FMT_UYVY:
665 dmr = 0;
666 output_is_yuv = true;
667 break;
668 case V4L2_PIX_FMT_RGB555X:
669 dmr = VNDMR_DTMD_ARGB1555;
670 break;
671 case V4L2_PIX_FMT_RGB565:
672 dmr = 0;
673 break;
674 case V4L2_PIX_FMT_RGB32:
2a9ecc17 675 if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 ||
ca0c9f17 676 priv->chip == RCAR_E1) {
73135e96
VB
677 dmr = VNDMR_EXRGB;
678 break;
679 }
680 default:
681 dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
682 icd->current_fmt->host_fmt->fourcc);
683 return -EINVAL;
684 }
685
686 /* Always update on field change */
687 vnmc |= VNMC_VUP;
688
689 /* If input and output use the same colorspace, use bypass mode */
920a1bf3 690 if (input_is_yuv == output_is_yuv)
73135e96
VB
691 vnmc |= VNMC_BPS;
692
693 /* progressive or interlaced mode */
e272d95f 694 interrupts = progressive ? VNIE_FIE : VNIE_EFE;
73135e96
VB
695
696 /* ack interrupts */
697 iowrite32(interrupts, priv->base + VNINTS_REG);
698 /* enable interrupts */
699 iowrite32(interrupts, priv->base + VNIE_REG);
700 /* start capturing */
701 iowrite32(dmr, priv->base + VNDMR_REG);
702 iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
703
704 return 0;
705}
706
707static void rcar_vin_capture(struct rcar_vin_priv *priv)
708{
709 if (is_continuous_transfer(priv))
710 /* Continuous Frame Capture Mode */
711 iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
712 else
713 /* Single Frame Capture Mode */
714 iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
715}
716
717static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
718{
719 priv->state = STOPPING;
720
721 /* set continuous & single transfer off */
722 iowrite32(0, priv->base + VNFC_REG);
723 /* disable capture (release DMA buffer), reset */
724 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
725 priv->base + VNMC_REG);
726
727 /* update the status if stopped already */
728 if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
729 priv->state = STOPPED;
730}
731
732static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
733{
734 int slot;
735
736 for (slot = 0; slot < priv->nr_hw_slots; slot++)
737 if (priv->queue_buf[slot] == NULL)
738 return slot;
739
740 return -1;
741}
742
743static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
744{
745 /* Ensure all HW slots are filled */
746 return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
747}
748
749/* Moves a buffer from the queue to the HW slots */
750static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
751{
2d700715 752 struct vb2_v4l2_buffer *vbuf;
73135e96
VB
753 dma_addr_t phys_addr_top;
754 int slot;
755
756 if (list_empty(&priv->capture))
757 return 0;
758
759 /* Find a free HW slot */
760 slot = rcar_vin_get_free_hw_slot(priv);
761 if (slot < 0)
762 return 0;
763
2d700715
JS
764 vbuf = &list_entry(priv->capture.next,
765 struct rcar_vin_buffer, list)->vb;
766 list_del_init(to_buf_list(vbuf));
767 priv->queue_buf[slot] = vbuf;
768 phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
73135e96
VB
769 iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
770
771 return 1;
772}
773
774static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
775{
2d700715 776 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
73135e96
VB
777 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
778 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
779 struct rcar_vin_priv *priv = ici->priv;
780 unsigned long size;
781
782 size = icd->sizeimage;
783
784 if (vb2_plane_size(vb, 0) < size) {
785 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
2d700715 786 vb->index, vb2_plane_size(vb, 0), size);
73135e96
VB
787 goto error;
788 }
789
790 vb2_set_plane_payload(vb, 0, size);
791
792 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
793 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
794
795 spin_lock_irq(&priv->lock);
796
2d700715 797 list_add_tail(to_buf_list(vbuf), &priv->capture);
73135e96
VB
798 rcar_vin_fill_hw_slot(priv);
799
800 /* If we weren't running, and have enough buffers, start capturing! */
801 if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
802 if (rcar_vin_setup(priv)) {
803 /* Submit error */
2d700715 804 list_del_init(to_buf_list(vbuf));
73135e96
VB
805 spin_unlock_irq(&priv->lock);
806 goto error;
807 }
808 priv->request_to_stop = false;
809 init_completion(&priv->capture_stop);
810 priv->state = RUNNING;
811 rcar_vin_capture(priv);
812 }
813
814 spin_unlock_irq(&priv->lock);
815
816 return;
817
818error:
819 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
820}
821
4abec468
IM
822/*
823 * Wait for capture to stop and all in-flight buffers to be finished with by
824 * the video hardware. This must be called under &priv->lock
825 *
826 */
827static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
828{
829 while (priv->state != STOPPED) {
830 /* issue stop if running */
831 if (priv->state == RUNNING)
832 rcar_vin_request_capture_stop(priv);
833
834 /* wait until capturing has been stopped */
835 if (priv->state == STOPPING) {
836 priv->request_to_stop = true;
837 spin_unlock_irq(&priv->lock);
5a9b06a2
KM
838 if (!wait_for_completion_timeout(
839 &priv->capture_stop,
840 msecs_to_jiffies(TIMEOUT_MS)))
841 priv->state = STOPPED;
4abec468
IM
842 spin_lock_irq(&priv->lock);
843 }
844 }
845}
846
e99f0115 847static void rcar_vin_stop_streaming(struct vb2_queue *vq)
73135e96 848{
e99f0115 849 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
73135e96
VB
850 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
851 struct rcar_vin_priv *priv = ici->priv;
e99f0115
WT
852 struct list_head *buf_head, *tmp;
853 int i;
73135e96
VB
854
855 spin_lock_irq(&priv->lock);
e99f0115 856 rcar_vin_wait_stop_streaming(priv);
73135e96 857
73135e96 858 for (i = 0; i < MAX_BUFFER_NUM; i++) {
e99f0115 859 if (priv->queue_buf[i]) {
2d700715 860 vb2_buffer_done(&priv->queue_buf[i]->vb2_buf,
73135e96 861 VB2_BUF_STATE_ERROR);
e99f0115 862 priv->queue_buf[i] = NULL;
73135e96 863 }
73135e96
VB
864 }
865
e99f0115
WT
866 list_for_each_safe(buf_head, tmp, &priv->capture) {
867 vb2_buffer_done(&list_entry(buf_head,
2d700715 868 struct rcar_vin_buffer, list)->vb.vb2_buf,
e99f0115 869 VB2_BUF_STATE_ERROR);
73135e96 870 list_del_init(buf_head);
e99f0115 871 }
73135e96 872 spin_unlock_irq(&priv->lock);
73135e96
VB
873}
874
875static struct vb2_ops rcar_vin_vb2_ops = {
876 .queue_setup = rcar_vin_videobuf_setup,
73135e96
VB
877 .buf_queue = rcar_vin_videobuf_queue,
878 .stop_streaming = rcar_vin_stop_streaming,
976036df
LP
879 .wait_prepare = vb2_ops_wait_prepare,
880 .wait_finish = vb2_ops_wait_finish,
73135e96
VB
881};
882
883static irqreturn_t rcar_vin_irq(int irq, void *data)
884{
885 struct rcar_vin_priv *priv = data;
886 u32 int_status;
887 bool can_run = false, hw_stopped;
888 int slot;
889 unsigned int handled = 0;
890
891 spin_lock(&priv->lock);
892
893 int_status = ioread32(priv->base + VNINTS_REG);
894 if (!int_status)
895 goto done;
896 /* ack interrupts */
897 iowrite32(int_status, priv->base + VNINTS_REG);
898 handled = 1;
899
900 /* nothing to do if capture status is 'STOPPED' */
901 if (priv->state == STOPPED)
902 goto done;
903
904 hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
905
906 if (!priv->request_to_stop) {
907 if (is_continuous_transfer(priv))
908 slot = (ioread32(priv->base + VNMS_REG) &
909 VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
910 else
911 slot = 0;
912
2d700715
JS
913 priv->queue_buf[slot]->field = priv->field;
914 priv->queue_buf[slot]->sequence = priv->sequence++;
915 v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp);
916 vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
917 VB2_BUF_STATE_DONE);
73135e96
VB
918 priv->queue_buf[slot] = NULL;
919
920 if (priv->state != STOPPING)
921 can_run = rcar_vin_fill_hw_slot(priv);
922
923 if (hw_stopped || !can_run) {
924 priv->state = STOPPED;
925 } else if (is_continuous_transfer(priv) &&
926 list_empty(&priv->capture) &&
927 priv->state == RUNNING) {
928 /*
929 * The continuous capturing requires an explicit stop
930 * operation when there is no buffer to be set into
931 * the VnMBm registers.
932 */
933 rcar_vin_request_capture_stop(priv);
934 } else {
935 rcar_vin_capture(priv);
936 }
937
938 } else if (hw_stopped) {
939 priv->state = STOPPED;
940 priv->request_to_stop = false;
941 complete(&priv->capture_stop);
942 }
943
944done:
945 spin_unlock(&priv->lock);
946
947 return IRQ_RETVAL(handled);
948}
949
950static int rcar_vin_add_device(struct soc_camera_device *icd)
951{
952 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
953 struct rcar_vin_priv *priv = ici->priv;
954 int i;
955
956 for (i = 0; i < MAX_BUFFER_NUM; i++)
957 priv->queue_buf[i] = NULL;
958
959 pm_runtime_get_sync(ici->v4l2_dev.dev);
960
961 dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
962 icd->devnum);
963
964 return 0;
965}
966
967static void rcar_vin_remove_device(struct soc_camera_device *icd)
968{
969 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
970 struct rcar_vin_priv *priv = ici->priv;
2d700715 971 struct vb2_v4l2_buffer *vbuf;
73135e96
VB
972 int i;
973
974 /* disable capture, disable interrupts */
975 iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
976 priv->base + VNMC_REG);
977 iowrite32(0, priv->base + VNIE_REG);
978
979 priv->state = STOPPED;
980 priv->request_to_stop = false;
981
982 /* make sure active buffer is cancelled */
983 spin_lock_irq(&priv->lock);
984 for (i = 0; i < MAX_BUFFER_NUM; i++) {
2d700715
JS
985 vbuf = priv->queue_buf[i];
986 if (vbuf) {
987 list_del_init(to_buf_list(vbuf));
988 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
73135e96
VB
989 }
990 }
991 spin_unlock_irq(&priv->lock);
992
993 pm_runtime_put(ici->v4l2_dev.dev);
994
995 dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
996 icd->devnum);
997}
998
4c28078c
KM
999static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
1000{
1001 int i;
1002 const struct vin_coeff *p_prev_set = NULL;
1003 const struct vin_coeff *p_set = NULL;
1004
1005 /* Look for suitable coefficient values */
1006 for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
1007 p_prev_set = p_set;
1008 p_set = &vin_coeff_set[i];
1009
1010 if (xs < p_set->xs_value)
1011 break;
1012 }
1013
1014 /* Use previous value if its XS value is closer */
1015 if (p_prev_set && p_set &&
1016 xs - p_prev_set->xs_value < p_set->xs_value - xs)
1017 p_set = p_prev_set;
1018
1019 /* Set coefficient registers */
1020 iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
1021 iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
1022 iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
1023
1024 iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
1025 iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
1026 iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
1027
1028 iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
1029 iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
1030 iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
1031
1032 iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
1033 iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
1034 iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
1035
1036 iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
1037 iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
1038 iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
1039
1040 iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
1041 iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
1042 iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
1043
1044 iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
1045 iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
1046 iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
1047
1048 iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
1049 iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
1050 iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
1051}
1052
73135e96
VB
1053/* rect is guaranteed to not exceed the scaled camera rectangle */
1054static int rcar_vin_set_rect(struct soc_camera_device *icd)
1055{
1056 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1057 struct rcar_vin_cam *cam = icd->host_priv;
1058 struct rcar_vin_priv *priv = ici->priv;
1059 unsigned int left_offset, top_offset;
1060 unsigned char dsize = 0;
1061 struct v4l2_rect *cam_subrect = &cam->subrect;
4c28078c 1062 u32 value;
73135e96
VB
1063
1064 dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
1065 icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
1066
1067 left_offset = cam->vin_left;
1068 top_offset = cam->vin_top;
1069
1070 if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 &&
1071 priv->chip == RCAR_E1)
1072 dsize = 1;
1073
1074 dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
1075 cam->width, cam->height, cam->vin_left, cam->vin_top);
1076 dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
1077 cam_subrect->width, cam_subrect->height,
1078 cam_subrect->left, cam_subrect->top);
1079
1080 /* Set Start/End Pixel/Line Pre-Clip */
1081 iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
4c28078c 1082 iowrite32((left_offset + cam_subrect->width - 1) << dsize,
73135e96
VB
1083 priv->base + VNEPPRC_REG);
1084 switch (priv->field) {
1085 case V4L2_FIELD_INTERLACED:
1086 case V4L2_FIELD_INTERLACED_TB:
1087 case V4L2_FIELD_INTERLACED_BT:
1088 iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
4c28078c 1089 iowrite32((top_offset + cam_subrect->height) / 2 - 1,
73135e96
VB
1090 priv->base + VNELPRC_REG);
1091 break;
1092 default:
1093 iowrite32(top_offset, priv->base + VNSLPRC_REG);
4c28078c 1094 iowrite32(top_offset + cam_subrect->height - 1,
73135e96
VB
1095 priv->base + VNELPRC_REG);
1096 break;
1097 }
1098
4c28078c
KM
1099 /* Set scaling coefficient */
1100 value = 0;
1101 if (cam_subrect->height != cam->out_height)
1102 value = (4096 * cam_subrect->height) / cam->out_height;
1103 dev_dbg(icd->parent, "YS Value: %x\n", value);
1104 iowrite32(value, priv->base + VNYS_REG);
1105
1106 value = 0;
1107 if (cam_subrect->width != cam->out_width)
1108 value = (4096 * cam_subrect->width) / cam->out_width;
1109
1110 /* Horizontal upscaling is up to double size */
1111 if (0 < value && value < 2048)
1112 value = 2048;
1113
1114 dev_dbg(icd->parent, "XS Value: %x\n", value);
1115 iowrite32(value, priv->base + VNXS_REG);
1116
1117 /* Horizontal upscaling is carried out by scaling down from double size */
1118 if (value < 4096)
1119 value *= 2;
1120
1121 set_coeff(priv, value);
1122
73135e96
VB
1123 /* Set Start/End Pixel/Line Post-Clip */
1124 iowrite32(0, priv->base + VNSPPOC_REG);
1125 iowrite32(0, priv->base + VNSLPOC_REG);
4c28078c 1126 iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
73135e96
VB
1127 switch (priv->field) {
1128 case V4L2_FIELD_INTERLACED:
1129 case V4L2_FIELD_INTERLACED_TB:
1130 case V4L2_FIELD_INTERLACED_BT:
4c28078c 1131 iowrite32(cam->out_height / 2 - 1,
73135e96
VB
1132 priv->base + VNELPOC_REG);
1133 break;
1134 default:
4c28078c 1135 iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
73135e96
VB
1136 break;
1137 }
1138
4c28078c 1139 iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
73135e96
VB
1140
1141 return 0;
1142}
1143
1144static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
1145{
1146 *vnmc = ioread32(priv->base + VNMC_REG);
1147 /* module disable */
1148 iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
1149}
1150
1151static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
1152{
1153 unsigned long timeout = jiffies + 10 * HZ;
1154
1155 /*
1156 * Wait until the end of the current frame. It can take a long time,
1157 * but if it has been aborted by a MRST1 reset, it should exit sooner.
1158 */
1159 while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
1160 time_before(jiffies, timeout))
1161 msleep(1);
1162
1163 if (time_after(jiffies, timeout)) {
1164 dev_err(priv->ici.v4l2_dev.dev,
1165 "Timeout waiting for frame end! Interface problem?\n");
1166 return;
1167 }
1168
1169 iowrite32(vnmc, priv->base + VNMC_REG);
1170}
1171
1172#define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \
1173 V4L2_MBUS_PCLK_SAMPLE_RISING | \
1174 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
1175 V4L2_MBUS_HSYNC_ACTIVE_LOW | \
1176 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
1177 V4L2_MBUS_VSYNC_ACTIVE_LOW | \
1178 V4L2_MBUS_DATA_ACTIVE_HIGH)
1179
1180static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
1181{
1182 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1183 struct rcar_vin_priv *priv = ici->priv;
1184 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1185 struct v4l2_mbus_config cfg;
1186 unsigned long common_flags;
1187 u32 vnmc;
1188 u32 val;
1189 int ret;
1190
1191 capture_stop_preserve(priv, &vnmc);
1192
1193 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1194 if (!ret) {
1195 common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1196 if (!common_flags) {
1197 dev_warn(icd->parent,
1198 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1199 cfg.flags, VIN_MBUS_FLAGS);
1200 return -EINVAL;
1201 }
1202 } else if (ret != -ENOIOCTLCMD) {
1203 return ret;
1204 } else {
1205 common_flags = VIN_MBUS_FLAGS;
1206 }
1207
1208 /* Make choises, based on platform preferences */
1209 if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1210 (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
25dfa02c 1211 if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
73135e96
VB
1212 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1213 else
1214 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1215 }
1216
1217 if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1218 (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
25dfa02c 1219 if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
73135e96
VB
1220 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1221 else
1222 common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1223 }
1224
1225 cfg.flags = common_flags;
1226 ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1227 if (ret < 0 && ret != -ENOIOCTLCMD)
1228 return ret;
1229
609f33c9 1230 val = VNDMR2_FTEV | VNDMR2_VLV(1);
73135e96
VB
1231 if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
1232 val |= VNDMR2_VPS;
1233 if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
1234 val |= VNDMR2_HPS;
1235 iowrite32(val, priv->base + VNDMR2_REG);
1236
1237 ret = rcar_vin_set_rect(icd);
1238 if (ret < 0)
1239 return ret;
1240
1241 capture_restore(priv, vnmc);
1242
1243 return 0;
1244}
1245
1246static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
1247 unsigned char buswidth)
1248{
1249 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1250 struct v4l2_mbus_config cfg;
1251 int ret;
1252
1253 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1254 if (ret == -ENOIOCTLCMD)
1255 return 0;
1256 else if (ret)
1257 return ret;
1258
1259 if (buswidth > 24)
1260 return -EINVAL;
1261
1262 /* check is there common mbus flags */
1263 ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1264 if (ret)
1265 return 0;
1266
1267 dev_warn(icd->parent,
1268 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1269 cfg.flags, VIN_MBUS_FLAGS);
1270
1271 return -EINVAL;
1272}
1273
1274static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1275{
1276 return fmt->packing == SOC_MBUS_PACKING_NONE ||
1277 (fmt->bits_per_sample > 8 &&
1278 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1279}
1280
1281static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
1282 {
1283 .fourcc = V4L2_PIX_FMT_NV16,
1284 .name = "NV16",
1285 .bits_per_sample = 8,
1286 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1287 .order = SOC_MBUS_ORDER_LE,
1288 .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
1289 },
e5d49a3e
KM
1290 {
1291 .fourcc = V4L2_PIX_FMT_YUYV,
1292 .name = "YUYV",
1293 .bits_per_sample = 16,
1294 .packing = SOC_MBUS_PACKING_NONE,
1295 .order = SOC_MBUS_ORDER_LE,
1296 .layout = SOC_MBUS_LAYOUT_PACKED,
1297 },
73135e96
VB
1298 {
1299 .fourcc = V4L2_PIX_FMT_UYVY,
1300 .name = "UYVY",
1301 .bits_per_sample = 16,
1302 .packing = SOC_MBUS_PACKING_NONE,
1303 .order = SOC_MBUS_ORDER_LE,
1304 .layout = SOC_MBUS_LAYOUT_PACKED,
1305 },
1306 {
1307 .fourcc = V4L2_PIX_FMT_RGB565,
1308 .name = "RGB565",
1309 .bits_per_sample = 16,
1310 .packing = SOC_MBUS_PACKING_NONE,
1311 .order = SOC_MBUS_ORDER_LE,
1312 .layout = SOC_MBUS_LAYOUT_PACKED,
1313 },
1314 {
1315 .fourcc = V4L2_PIX_FMT_RGB555X,
1316 .name = "ARGB1555",
1317 .bits_per_sample = 16,
1318 .packing = SOC_MBUS_PACKING_NONE,
1319 .order = SOC_MBUS_ORDER_LE,
1320 .layout = SOC_MBUS_LAYOUT_PACKED,
1321 },
1322 {
1323 .fourcc = V4L2_PIX_FMT_RGB32,
1324 .name = "RGB888",
1325 .bits_per_sample = 32,
1326 .packing = SOC_MBUS_PACKING_NONE,
1327 .order = SOC_MBUS_ORDER_LE,
1328 .layout = SOC_MBUS_LAYOUT_PACKED,
1329 },
1330};
1331
1332static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
1333 struct soc_camera_format_xlate *xlate)
1334{
1335 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1336 struct device *dev = icd->parent;
1337 int ret, k, n;
1338 int formats = 0;
1339 struct rcar_vin_cam *cam;
ebcff5fc
HV
1340 struct v4l2_subdev_mbus_code_enum code = {
1341 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1342 .index = idx,
1343 };
73135e96
VB
1344 const struct soc_mbus_pixelfmt *fmt;
1345
ebcff5fc 1346 ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
73135e96
VB
1347 if (ret < 0)
1348 return 0;
1349
ebcff5fc 1350 fmt = soc_mbus_get_fmtdesc(code.code);
73135e96 1351 if (!fmt) {
ebcff5fc 1352 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
73135e96
VB
1353 return 0;
1354 }
1355
1356 ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1357 if (ret < 0)
1358 return 0;
1359
1360 if (!icd->host_priv) {
da298c6d
HV
1361 struct v4l2_subdev_format fmt = {
1362 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1363 };
1364 struct v4l2_mbus_framefmt *mf = &fmt.format;
73135e96
VB
1365 struct v4l2_rect rect;
1366 struct device *dev = icd->parent;
1367 int shift;
1368
da298c6d 1369 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
73135e96
VB
1370 if (ret < 0)
1371 return ret;
1372
1373 /* Cache current client geometry */
1374 ret = soc_camera_client_g_rect(sd, &rect);
1375 if (ret == -ENOIOCTLCMD) {
1376 /* Sensor driver doesn't support cropping */
1377 rect.left = 0;
1378 rect.top = 0;
da298c6d
HV
1379 rect.width = mf->width;
1380 rect.height = mf->height;
73135e96
VB
1381 } else if (ret < 0) {
1382 return ret;
1383 }
1384
1385 /*
1386 * If sensor proposes too large format then try smaller ones:
1387 * 1280x960, 640x480, 320x240
1388 */
1389 for (shift = 0; shift < 3; shift++) {
da298c6d
HV
1390 if (mf->width <= VIN_MAX_WIDTH &&
1391 mf->height <= VIN_MAX_HEIGHT)
73135e96
VB
1392 break;
1393
da298c6d
HV
1394 mf->width = 1280 >> shift;
1395 mf->height = 960 >> shift;
73135e96
VB
1396 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1397 soc_camera_grp_id(icd),
ebf984bb
HV
1398 pad, set_fmt, NULL,
1399 &fmt);
73135e96
VB
1400 if (ret < 0)
1401 return ret;
1402 }
1403
1404 if (shift == 3) {
1405 dev_err(dev,
197a47f2 1406 "Failed to configure the client below %ux%u\n",
da298c6d 1407 mf->width, mf->height);
73135e96
VB
1408 return -EIO;
1409 }
1410
da298c6d 1411 dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
73135e96
VB
1412
1413 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1414 if (!cam)
1415 return -ENOMEM;
1416 /*
1417 * We are called with current camera crop,
1418 * initialise subrect with it
1419 */
1420 cam->rect = rect;
1421 cam->subrect = rect;
da298c6d
HV
1422 cam->width = mf->width;
1423 cam->height = mf->height;
1424 cam->out_width = mf->width;
1425 cam->out_height = mf->height;
73135e96
VB
1426
1427 icd->host_priv = cam;
1428 } else {
1429 cam = icd->host_priv;
1430 }
1431
1432 /* Beginning of a pass */
1433 if (!idx)
1434 cam->extra_fmt = NULL;
1435
ebcff5fc 1436 switch (code.code) {
27ffaeb0
BB
1437 case MEDIA_BUS_FMT_YUYV8_1X16:
1438 case MEDIA_BUS_FMT_YUYV8_2X8:
1439 case MEDIA_BUS_FMT_YUYV10_2X10:
920a1bf3 1440 case MEDIA_BUS_FMT_RGB888_1X24:
73135e96
VB
1441 if (cam->extra_fmt)
1442 break;
1443
1444 /* Add all our formats that can be generated by VIN */
1445 cam->extra_fmt = rcar_vin_formats;
1446
1447 n = ARRAY_SIZE(rcar_vin_formats);
1448 formats += n;
1449 for (k = 0; xlate && k < n; k++, xlate++) {
1450 xlate->host_fmt = &rcar_vin_formats[k];
ebcff5fc 1451 xlate->code = code.code;
73135e96 1452 dev_dbg(dev, "Providing format %s using code %d\n",
ebcff5fc 1453 rcar_vin_formats[k].name, code.code);
73135e96
VB
1454 }
1455 break;
1456 default:
1457 if (!rcar_vin_packing_supported(fmt))
1458 return 0;
1459
1460 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1461 fmt->name);
1462 break;
1463 }
1464
1465 /* Generic pass-through */
1466 formats++;
1467 if (xlate) {
1468 xlate->host_fmt = fmt;
ebcff5fc 1469 xlate->code = code.code;
73135e96
VB
1470 xlate++;
1471 }
1472
1473 return formats;
1474}
1475
1476static void rcar_vin_put_formats(struct soc_camera_device *icd)
1477{
1478 kfree(icd->host_priv);
1479 icd->host_priv = NULL;
1480}
1481
1482static int rcar_vin_set_crop(struct soc_camera_device *icd,
1483 const struct v4l2_crop *a)
1484{
1485 struct v4l2_crop a_writable = *a;
1486 const struct v4l2_rect *rect = &a_writable.c;
1487 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1488 struct rcar_vin_priv *priv = ici->priv;
1489 struct v4l2_crop cam_crop;
1490 struct rcar_vin_cam *cam = icd->host_priv;
1491 struct v4l2_rect *cam_rect = &cam_crop.c;
1492 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1493 struct device *dev = icd->parent;
da298c6d
HV
1494 struct v4l2_subdev_format fmt = {
1495 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1496 };
1497 struct v4l2_mbus_framefmt *mf = &fmt.format;
73135e96
VB
1498 u32 vnmc;
1499 int ret, i;
1500
1501 dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
1502 rect->left, rect->top);
1503
1504 /* During camera cropping its output window can change too, stop VIN */
1505 capture_stop_preserve(priv, &vnmc);
1506 dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1507
1508 /* Apply iterative camera S_CROP for new input window. */
1509 ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
1510 &cam->rect, &cam->subrect);
1511 if (ret < 0)
1512 return ret;
1513
1514 dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
1515 cam_rect->width, cam_rect->height,
1516 cam_rect->left, cam_rect->top);
1517
1518 /* On success cam_crop contains current camera crop */
1519
1520 /* Retrieve camera output window */
da298c6d 1521 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
73135e96
VB
1522 if (ret < 0)
1523 return ret;
1524
da298c6d 1525 if (mf->width > VIN_MAX_WIDTH || mf->height > VIN_MAX_HEIGHT)
73135e96
VB
1526 return -EINVAL;
1527
1528 /* Cache camera output window */
da298c6d
HV
1529 cam->width = mf->width;
1530 cam->height = mf->height;
73135e96
VB
1531
1532 icd->user_width = cam->width;
1533 icd->user_height = cam->height;
1534
1535 cam->vin_left = rect->left & ~1;
1536 cam->vin_top = rect->top & ~1;
1537
1538 /* Use VIN cropping to crop to the new window. */
1539 ret = rcar_vin_set_rect(icd);
1540 if (ret < 0)
1541 return ret;
1542
1543 cam->subrect = *rect;
1544
1545 dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
1546 icd->user_width, icd->user_height,
1547 cam->vin_left, cam->vin_top);
1548
1549 /* Restore capture */
1550 for (i = 0; i < MAX_BUFFER_NUM; i++) {
1551 if (priv->queue_buf[i] && priv->state == STOPPED) {
1552 vnmc |= VNMC_ME;
1553 break;
1554 }
1555 }
1556 capture_restore(priv, vnmc);
1557
1558 /* Even if only camera cropping succeeded */
1559 return ret;
1560}
1561
1562static int rcar_vin_get_crop(struct soc_camera_device *icd,
1563 struct v4l2_crop *a)
1564{
1565 struct rcar_vin_cam *cam = icd->host_priv;
1566
1567 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1568 a->c = cam->subrect;
1569
1570 return 0;
1571}
1572
1573/* Similar to set_crop multistage iterative algorithm */
1574static int rcar_vin_set_fmt(struct soc_camera_device *icd,
1575 struct v4l2_format *f)
1576{
1577 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1578 struct rcar_vin_priv *priv = ici->priv;
1579 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1580 struct rcar_vin_cam *cam = icd->host_priv;
1581 struct v4l2_pix_format *pix = &f->fmt.pix;
1582 struct v4l2_mbus_framefmt mf;
1583 struct device *dev = icd->parent;
1584 __u32 pixfmt = pix->pixelformat;
1585 const struct soc_camera_format_xlate *xlate;
1586 unsigned int vin_sub_width = 0, vin_sub_height = 0;
1587 int ret;
1588 bool can_scale;
1589 enum v4l2_field field;
1590 v4l2_std_id std;
1591
1592 dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
1593 pixfmt, pix->width, pix->height);
1594
1595 switch (pix->field) {
1596 default:
1597 pix->field = V4L2_FIELD_NONE;
1598 /* fall-through */
1599 case V4L2_FIELD_NONE:
1600 case V4L2_FIELD_TOP:
1601 case V4L2_FIELD_BOTTOM:
1602 case V4L2_FIELD_INTERLACED_TB:
1603 case V4L2_FIELD_INTERLACED_BT:
1604 field = pix->field;
1605 break;
1606 case V4L2_FIELD_INTERLACED:
ca739eb0
MCC
1607 /* Query for standard if not explicitly mentioned _TB/_BT */
1608 ret = v4l2_subdev_call(sd, video, querystd, &std);
936ad890
SS
1609 if (ret == -ENOIOCTLCMD) {
1610 field = V4L2_FIELD_NONE;
1611 } else if (ret < 0) {
1612 return ret;
1613 } else {
1614 field = std & V4L2_STD_625_50 ?
1615 V4L2_FIELD_INTERLACED_TB :
1616 V4L2_FIELD_INTERLACED_BT;
1617 }
73135e96
VB
1618 break;
1619 }
1620
1621 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1622 if (!xlate) {
1623 dev_warn(dev, "Format %x not found\n", pixfmt);
1624 return -EINVAL;
1625 }
1626 /* Calculate client output geometry */
1627 soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1628 12);
1629 mf.field = pix->field;
1630 mf.colorspace = pix->colorspace;
1631 mf.code = xlate->code;
1632
1633 switch (pixfmt) {
1634 case V4L2_PIX_FMT_RGB32:
1635 can_scale = priv->chip != RCAR_E1;
1636 break;
1637 case V4L2_PIX_FMT_UYVY:
1638 case V4L2_PIX_FMT_YUYV:
1639 case V4L2_PIX_FMT_RGB565:
1640 case V4L2_PIX_FMT_RGB555X:
1641 can_scale = true;
1642 break;
1643 default:
1644 can_scale = false;
1645 break;
1646 }
1647
1648 dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1649
1650 ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1651 &mf, &vin_sub_width, &vin_sub_height,
1652 can_scale, 12);
1653
1654 /* Done with the camera. Now see if we can improve the result */
1655 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1656 ret, mf.width, mf.height, pix->width, pix->height);
1657
1658 if (ret == -ENOIOCTLCMD)
1659 dev_dbg(dev, "Sensor doesn't support scaling\n");
1660 else if (ret < 0)
1661 return ret;
1662
1663 if (mf.code != xlate->code)
1664 return -EINVAL;
1665
1666 /* Prepare VIN crop */
1667 cam->width = mf.width;
1668 cam->height = mf.height;
1669
1670 /* Use VIN scaling to scale to the requested user window. */
1671
1672 /* We cannot scale up */
1673 if (pix->width > vin_sub_width)
1674 vin_sub_width = pix->width;
1675
1676 if (pix->height > vin_sub_height)
1677 vin_sub_height = pix->height;
1678
1679 pix->colorspace = mf.colorspace;
1680
1681 if (!can_scale) {
1682 pix->width = vin_sub_width;
1683 pix->height = vin_sub_height;
1684 }
1685
1686 /*
1687 * We have calculated CFLCR, the actual configuration will be performed
1688 * in rcar_vin_set_bus_param()
1689 */
1690
1691 dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1692 vin_sub_width, pix->width, vin_sub_height, pix->height);
1693
4c28078c
KM
1694 cam->out_width = pix->width;
1695 cam->out_height = pix->height;
1696
73135e96
VB
1697 icd->current_fmt = xlate;
1698
1699 priv->field = field;
1700
1701 return 0;
1702}
1703
1704static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1705 struct v4l2_format *f)
1706{
1707 const struct soc_camera_format_xlate *xlate;
1708 struct v4l2_pix_format *pix = &f->fmt.pix;
1709 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
5eab4983
HV
1710 struct v4l2_subdev_pad_config pad_cfg;
1711 struct v4l2_subdev_format format = {
1712 .which = V4L2_SUBDEV_FORMAT_TRY,
1713 };
1714 struct v4l2_mbus_framefmt *mf = &format.format;
73135e96
VB
1715 __u32 pixfmt = pix->pixelformat;
1716 int width, height;
1717 int ret;
1718
1719 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1720 if (!xlate) {
1721 xlate = icd->current_fmt;
1722 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1723 pixfmt, xlate->host_fmt->fourcc);
1724 pixfmt = xlate->host_fmt->fourcc;
1725 pix->pixelformat = pixfmt;
1726 pix->colorspace = icd->colorspace;
1727 }
1728
1729 /* FIXME: calculate using depth and bus width */
1730 v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1731 &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1732
1733 width = pix->width;
1734 height = pix->height;
1735
1736 /* let soc-camera calculate these values */
1737 pix->bytesperline = 0;
1738 pix->sizeimage = 0;
1739
1740 /* limit to sensor capabilities */
5eab4983
HV
1741 mf->width = pix->width;
1742 mf->height = pix->height;
1743 mf->field = pix->field;
1744 mf->code = xlate->code;
1745 mf->colorspace = pix->colorspace;
73135e96
VB
1746
1747 ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
5eab4983 1748 pad, set_fmt, &pad_cfg, &format);
73135e96
VB
1749 if (ret < 0)
1750 return ret;
1751
4c28078c 1752 /* Adjust only if VIN cannot scale */
5eab4983
HV
1753 if (pix->width > mf->width * 2)
1754 pix->width = mf->width * 2;
1755 if (pix->height > mf->height * 3)
1756 pix->height = mf->height * 3;
4c28078c 1757
5eab4983
HV
1758 pix->field = mf->field;
1759 pix->colorspace = mf->colorspace;
73135e96
VB
1760
1761 if (pixfmt == V4L2_PIX_FMT_NV16) {
1762 /* FIXME: check against rect_max after converting soc-camera */
1763 /* We can scale precisely, need a bigger image from camera */
1764 if (pix->width < width || pix->height < height) {
1765 /*
1766 * We presume, the sensor behaves sanely, i.e. if
1767 * requested a bigger rectangle, it will not return a
1768 * smaller one.
1769 */
5eab4983
HV
1770 mf->width = VIN_MAX_WIDTH;
1771 mf->height = VIN_MAX_HEIGHT;
73135e96
VB
1772 ret = v4l2_device_call_until_err(sd->v4l2_dev,
1773 soc_camera_grp_id(icd),
5eab4983
HV
1774 pad, set_fmt, &pad_cfg,
1775 &format);
73135e96
VB
1776 if (ret < 0) {
1777 dev_err(icd->parent,
1778 "client try_fmt() = %d\n", ret);
1779 return ret;
1780 }
1781 }
1782 /* We will scale exactly */
5eab4983 1783 if (mf->width > width)
73135e96 1784 pix->width = width;
5eab4983 1785 if (mf->height > height)
73135e96
VB
1786 pix->height = height;
1787 }
1788
1789 return ret;
1790}
1791
1792static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1793{
1794 struct soc_camera_device *icd = file->private_data;
1795
1796 return vb2_poll(&icd->vb2_vidq, file, pt);
1797}
1798
1799static int rcar_vin_querycap(struct soc_camera_host *ici,
1800 struct v4l2_capability *cap)
1801{
1802 strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
42d74e4f
NI
1803 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1804 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
734f3f23 1805 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr);
42d74e4f 1806
73135e96
VB
1807 return 0;
1808}
1809
1810static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1811 struct soc_camera_device *icd)
1812{
976036df
LP
1813 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1814
73135e96
VB
1815 vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1816 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1817 vq->drv_priv = icd;
1818 vq->ops = &rcar_vin_vb2_ops;
1819 vq->mem_ops = &vb2_dma_contig_memops;
1820 vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
ade48681 1821 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
976036df 1822 vq->lock = &ici->host_lock;
73135e96
VB
1823
1824 return vb2_queue_init(vq);
1825}
1826
1827static struct soc_camera_host_ops rcar_vin_host_ops = {
1828 .owner = THIS_MODULE,
1829 .add = rcar_vin_add_device,
1830 .remove = rcar_vin_remove_device,
73135e96
VB
1831 .get_formats = rcar_vin_get_formats,
1832 .put_formats = rcar_vin_put_formats,
1833 .get_crop = rcar_vin_get_crop,
1834 .set_crop = rcar_vin_set_crop,
1835 .try_fmt = rcar_vin_try_fmt,
1836 .set_fmt = rcar_vin_set_fmt,
1837 .poll = rcar_vin_poll,
1838 .querycap = rcar_vin_querycap,
1839 .set_bus_param = rcar_vin_set_bus_param,
1840 .init_videobuf2 = rcar_vin_init_videobuf2,
1841};
1842
47c71bd6 1843#ifdef CONFIG_OF
7f099a75 1844static const struct of_device_id rcar_vin_of_table[] = {
76deaff8
YK
1845 { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1846 { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
47c71bd6
BD
1847 { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1848 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1849 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1850 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1851 { },
1852};
1853MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1854#endif
1855
73135e96
VB
1856static struct platform_device_id rcar_vin_id_table[] = {
1857 { "r8a7779-vin", RCAR_H1 },
1858 { "r8a7778-vin", RCAR_M1 },
1859 { "uPD35004-vin", RCAR_E1 },
1860 {},
1861};
1862MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
1863
1864static int rcar_vin_probe(struct platform_device *pdev)
1865{
47c71bd6 1866 const struct of_device_id *match = NULL;
73135e96
VB
1867 struct rcar_vin_priv *priv;
1868 struct resource *mem;
1869 struct rcar_vin_platform_data *pdata;
47c71bd6 1870 unsigned int pdata_flags;
73135e96
VB
1871 int irq, ret;
1872
47c71bd6
BD
1873 if (pdev->dev.of_node) {
1874 struct v4l2_of_endpoint ep;
1875 struct device_node *np;
1876
1877 match = of_match_device(of_match_ptr(rcar_vin_of_table),
1878 &pdev->dev);
1879
1880 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1881 if (!np) {
1882 dev_err(&pdev->dev, "could not find endpoint\n");
1883 return -EINVAL;
1884 }
1885
1886 ret = v4l2_of_parse_endpoint(np, &ep);
1887 if (ret) {
1888 dev_err(&pdev->dev, "could not parse endpoint\n");
1889 return ret;
1890 }
1891
1892 if (ep.bus_type == V4L2_MBUS_BT656)
1893 pdata_flags = RCAR_VIN_BT656;
1894 else {
1895 pdata_flags = 0;
1896 if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1897 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1898 if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1899 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1900 }
1901
1902 of_node_put(np);
1903
1904 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1905 } else {
1906 pdata = pdev->dev.platform_data;
1907 if (!pdata || !pdata->flags) {
1908 dev_err(&pdev->dev, "platform data not set\n");
1909 return -EINVAL;
1910 }
1911 pdata_flags = pdata->flags;
73135e96
VB
1912 }
1913
1914 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1915 if (mem == NULL)
1916 return -EINVAL;
1917
1918 irq = platform_get_irq(pdev, 0);
1919 if (irq <= 0)
1920 return -EINVAL;
1921
1922 priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1923 GFP_KERNEL);
1924 if (!priv)
1925 return -ENOMEM;
1926
1927 priv->base = devm_ioremap_resource(&pdev->dev, mem);
1928 if (IS_ERR(priv->base))
1929 return PTR_ERR(priv->base);
1930
1931 ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1932 dev_name(&pdev->dev), priv);
1933 if (ret)
1934 return ret;
1935
1936 priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1937 if (IS_ERR(priv->alloc_ctx))
1938 return PTR_ERR(priv->alloc_ctx);
1939
1940 priv->ici.priv = priv;
1941 priv->ici.v4l2_dev.dev = &pdev->dev;
73135e96
VB
1942 priv->ici.drv_name = dev_name(&pdev->dev);
1943 priv->ici.ops = &rcar_vin_host_ops;
1944
47c71bd6
BD
1945 priv->pdata_flags = pdata_flags;
1946 if (!match) {
1947 priv->ici.nr = pdev->id;
1948 priv->chip = pdev->id_entry->driver_data;
1949 } else {
1950 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1951 priv->chip = (enum chip_id)match->data;
c611c908 1952 }
47c71bd6 1953
73135e96
VB
1954 spin_lock_init(&priv->lock);
1955 INIT_LIST_HEAD(&priv->capture);
1956
1957 priv->state = STOPPED;
1958
1959 pm_suspend_ignore_children(&pdev->dev, true);
1960 pm_runtime_enable(&pdev->dev);
1961
1962 ret = soc_camera_host_register(&priv->ici);
1963 if (ret)
1964 goto cleanup;
1965
1966 return 0;
1967
1968cleanup:
1969 pm_runtime_disable(&pdev->dev);
1970 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1971
1972 return ret;
1973}
1974
1975static int rcar_vin_remove(struct platform_device *pdev)
1976{
1977 struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1978 struct rcar_vin_priv *priv = container_of(soc_host,
1979 struct rcar_vin_priv, ici);
1980
1981 soc_camera_host_unregister(soc_host);
1982 pm_runtime_disable(&pdev->dev);
1983 vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1984
1985 return 0;
1986}
1987
1988static struct platform_driver rcar_vin_driver = {
1989 .probe = rcar_vin_probe,
1990 .remove = rcar_vin_remove,
1991 .driver = {
1992 .name = DRV_NAME,
47c71bd6 1993 .of_match_table = of_match_ptr(rcar_vin_of_table),
73135e96
VB
1994 },
1995 .id_table = rcar_vin_id_table,
1996};
1997
1998module_platform_driver(rcar_vin_driver);
1999
2000MODULE_LICENSE("GPL");
2001MODULE_ALIAS("platform:rcar_vin");
2002MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
This page took 0.294224 seconds and 5 git commands to generate.