Version:  2.0.40 2.2.26 2.4.37 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0

Linux/drivers/media/platform/soc_camera/rcar_vin.c

  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>
 19 #include <linux/io.h>
 20 #include <linux/kernel.h>
 21 #include <linux/module.h>
 22 #include <linux/of.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>
 29 
 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>
 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 */
 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 */
 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)
 98 #define VNMC_INF_YUV10_BT656    (2 << 16)
 99 #define VNMC_INF_YUV10_BT601    (3 << 16)
100 #define VNMC_INF_YUV16          (5 << 16)
101 #define VNMC_VUP                (1 << 10)
102 #define VNMC_IM_ODD             (0 << 3)
103 #define VNMC_IM_ODD_EVEN        (1 << 3)
104 #define VNMC_IM_EVEN            (2 << 3)
105 #define VNMC_IM_FULL            (3 << 3)
106 #define VNMC_BPS                (1 << 1)
107 #define VNMC_ME                 (1 << 0)
108 
109 /* Video n Module Status Register bits */
110 #define VNMS_FBS_MASK           (3 << 3)
111 #define VNMS_FBS_SHIFT          3
112 #define VNMS_AV                 (1 << 1)
113 #define VNMS_CA                 (1 << 0)
114 
115 /* Video n Frame Capture Register bits */
116 #define VNFC_C_FRAME            (1 << 1)
117 #define VNFC_S_FRAME            (1 << 0)
118 
119 /* Video n Interrupt Enable Register bits */
120 #define VNIE_FIE                (1 << 4)
121 #define VNIE_EFE                (1 << 1)
122 
123 /* Video n Data Mode Register bits */
124 #define VNDMR_EXRGB             (1 << 8)
125 #define VNDMR_BPSM              (1 << 4)
126 #define VNDMR_DTMD_YCSEP        (1 << 1)
127 #define VNDMR_DTMD_ARGB1555     (1 << 0)
128 
129 /* Video n Data Mode Register 2 bits */
130 #define VNDMR2_VPS              (1 << 30)
131 #define VNDMR2_HPS              (1 << 29)
132 #define VNDMR2_FTEV             (1 << 17)
133 #define VNDMR2_VLV(n)           ((n & 0xf) << 12)
134 
135 #define VIN_MAX_WIDTH           2048
136 #define VIN_MAX_HEIGHT          2048
137 
138 enum chip_id {
139         RCAR_GEN2,
140         RCAR_H1,
141         RCAR_M1,
142         RCAR_E1,
143 };
144 
145 struct vin_coeff {
146         unsigned short xs_value;
147         u32 coeff_set[24];
148 };
149 
150 static const struct vin_coeff vin_coeff_set[] = {
151         { 0x0000, {
152                 0x00000000,             0x00000000,             0x00000000,
153                 0x00000000,             0x00000000,             0x00000000,
154                 0x00000000,             0x00000000,             0x00000000,
155                 0x00000000,             0x00000000,             0x00000000,
156                 0x00000000,             0x00000000,             0x00000000,
157                 0x00000000,             0x00000000,             0x00000000,
158                 0x00000000,             0x00000000,             0x00000000,
159                 0x00000000,             0x00000000,             0x00000000 },
160         },
161         { 0x1000, {
162                 0x000fa400,             0x000fa400,             0x09625902,
163                 0x000003f8,             0x00000403,             0x3de0d9f0,
164                 0x001fffed,             0x00000804,             0x3cc1f9c3,
165                 0x001003de,             0x00000c01,             0x3cb34d7f,
166                 0x002003d2,             0x00000c00,             0x3d24a92d,
167                 0x00200bca,             0x00000bff,             0x3df600d2,
168                 0x002013cc,             0x000007ff,             0x3ed70c7e,
169                 0x00100fde,             0x00000000,             0x3f87c036 },
170         },
171         { 0x1200, {
172                 0x002ffff1,             0x002ffff1,             0x02a0a9c8,
173                 0x002003e7,             0x001ffffa,             0x000185bc,
174                 0x002007dc,             0x000003ff,             0x3e52859c,
175                 0x00200bd4,             0x00000002,             0x3d53996b,
176                 0x00100fd0,             0x00000403,             0x3d04ad2d,
177                 0x00000bd5,             0x00000403,             0x3d35ace7,
178                 0x3ff003e4,             0x00000801,             0x3dc674a1,
179                 0x3fffe800,             0x00000800,             0x3e76f461 },
180         },
181         { 0x1400, {
182                 0x00100be3,             0x00100be3,             0x04d1359a,
183                 0x00000fdb,             0x002003ed,             0x0211fd93,
184                 0x00000fd6,             0x002003f4,             0x0002d97b,
185                 0x000007d6,             0x002ffffb,             0x3e93b956,
186                 0x3ff003da,             0x001003ff,             0x3db49926,
187                 0x3fffefe9,             0x00100001,             0x3d655cee,
188                 0x3fffd400,             0x00000003,             0x3d65f4b6,
189                 0x000fb421,             0x00000402,             0x3dc6547e },
190         },
191         { 0x1600, {
192                 0x00000bdd,             0x00000bdd,             0x06519578,
193                 0x3ff007da,             0x00000be3,             0x03c24973,
194                 0x3ff003d9,             0x00000be9,             0x01b30d5f,
195                 0x3ffff7df,             0x001003f1,             0x0003c542,
196                 0x000fdfec,             0x001003f7,             0x3ec4711d,
197                 0x000fc400,             0x002ffffd,             0x3df504f1,
198                 0x001fa81a,             0x002ffc00,             0x3d957cc2,
199                 0x002f8c3c,             0x00100000,             0x3db5c891 },
200         },
201         { 0x1800, {
202                 0x3ff003dc,             0x3ff003dc,             0x0791e558,
203                 0x000ff7dd,             0x3ff007de,             0x05328554,
204                 0x000fe7e3,             0x3ff00be2,             0x03232546,
205                 0x000fd7ee,             0x000007e9,             0x0143bd30,
206                 0x001fb800,             0x000007ee,             0x00044511,
207                 0x002fa015,             0x000007f4,             0x3ef4bcee,
208                 0x002f8832,             0x001003f9,             0x3e4514c7,
209                 0x001f7853,             0x001003fd,             0x3de54c9f },
210         },
211         { 0x1a00, {
212                 0x000fefe0,             0x000fefe0,             0x08721d3c,
213                 0x001fdbe7,             0x000ffbde,             0x0652a139,
214                 0x001fcbf0,             0x000003df,             0x0463292e,
215                 0x002fb3ff,             0x3ff007e3,             0x0293a91d,
216                 0x002f9c12,             0x3ff00be7,             0x01241905,
217                 0x001f8c29,             0x000007ed,             0x3fe470eb,
218                 0x000f7c46,             0x000007f2,             0x3f04b8ca,
219                 0x3fef7865,             0x000007f6,             0x3e74e4a8 },
220         },
221         { 0x1c00, {
222                 0x001fd3e9,             0x001fd3e9,             0x08f23d26,
223                 0x002fbff3,             0x001fe3e4,             0x0712ad23,
224                 0x002fa800,             0x000ff3e0,             0x05631d1b,
225                 0x001f9810,             0x000ffbe1,             0x03b3890d,
226                 0x000f8c23,             0x000003e3,             0x0233e8fa,
227                 0x3fef843b,             0x000003e7,             0x00f430e4,
228                 0x3fbf8456,             0x3ff00bea,             0x00046cc8,
229                 0x3f8f8c72,             0x3ff00bef,             0x3f3490ac },
230         },
231         { 0x1e00, {
232                 0x001fbbf4,             0x001fbbf4,             0x09425112,
233                 0x001fa800,             0x002fc7ed,             0x0792b110,
234                 0x000f980e,             0x001fdbe6,             0x0613110a,
235                 0x3fff8c20,             0x001fe7e3,             0x04a368fd,
236                 0x3fcf8c33,             0x000ff7e2,             0x0343b8ed,
237                 0x3f9f8c4a,             0x000fffe3,             0x0203f8da,
238                 0x3f5f9c61,             0x000003e6,             0x00e428c5,
239                 0x3f1fb07b,             0x000003eb,             0x3fe440af },
240         },
241         { 0x2000, {
242                 0x000fa400,             0x000fa400,             0x09625902,
243                 0x3fff980c,             0x001fb7f5,             0x0812b0ff,
244                 0x3fdf901c,             0x001fc7ed,             0x06b2fcfa,
245                 0x3faf902d,             0x001fd3e8,             0x055348f1,
246                 0x3f7f983f,             0x001fe3e5,             0x04038ce3,
247                 0x3f3fa454,             0x001fefe3,             0x02e3c8d1,
248                 0x3f0fb86a,             0x001ff7e4,             0x01c3e8c0,
249                 0x3ecfd880,             0x000fffe6,             0x00c404ac },
250         },
251         { 0x2200, {
252                 0x3fdf9c0b,             0x3fdf9c0b,             0x09725cf4,
253                 0x3fbf9818,             0x3fffa400,             0x0842a8f1,
254                 0x3f8f9827,             0x000fb3f7,             0x0702f0ec,
255                 0x3f5fa037,             0x000fc3ef,             0x05d330e4,
256                 0x3f2fac49,             0x001fcfea,             0x04a364d9,
257                 0x3effc05c,             0x001fdbe7,             0x038394ca,
258                 0x3ecfdc6f,             0x001fe7e6,             0x0273b0bb,
259                 0x3ea00083,             0x001fefe6,             0x0183c0a9 },
260         },
261         { 0x2400, {
262                 0x3f9fa014,             0x3f9fa014,             0x098260e6,
263                 0x3f7f9c23,             0x3fcf9c0a,             0x08629ce5,
264                 0x3f4fa431,             0x3fefa400,             0x0742d8e1,
265                 0x3f1fb440,             0x3fffb3f8,             0x062310d9,
266                 0x3eefc850,             0x000fbbf2,             0x050340d0,
267                 0x3ecfe062,             0x000fcbec,             0x041364c2,
268                 0x3ea00073,             0x001fd3ea,             0x03037cb5,
269                 0x3e902086,             0x001fdfe8,             0x022388a5 },
270         },
271         { 0x2600, {
272                 0x3f5fa81e,             0x3f5fa81e,             0x096258da,
273                 0x3f3fac2b,             0x3f8fa412,             0x088290d8,
274                 0x3f0fbc38,             0x3fafa408,             0x0772c8d5,
275                 0x3eefcc47,             0x3fcfa800,             0x0672f4ce,
276                 0x3ecfe456,             0x3fefaffa,             0x05531cc6,
277                 0x3eb00066,             0x3fffbbf3,             0x047334bb,
278                 0x3ea01c77,             0x000fc7ee,             0x039348ae,
279                 0x3ea04486,             0x000fd3eb,             0x02b350a1 },
280         },
281         { 0x2800, {
282                 0x3f2fb426,             0x3f2fb426,             0x094250ce,
283                 0x3f0fc032,             0x3f4fac1b,             0x086284cd,
284                 0x3eefd040,             0x3f7fa811,             0x0782acc9,
285                 0x3ecfe84c,             0x3f9fa807,             0x06a2d8c4,
286                 0x3eb0005b,             0x3fbfac00,             0x05b2f4bc,
287                 0x3eb0186a,             0x3fdfb3fa,             0x04c308b4,
288                 0x3eb04077,             0x3fefbbf4,             0x03f31ca8,
289                 0x3ec06884,             0x000fbff2,             0x03031c9e },
290         },
291         { 0x2a00, {
292                 0x3f0fc42d,             0x3f0fc42d,             0x090240c4,
293                 0x3eefd439,             0x3f2fb822,             0x08526cc2,
294                 0x3edfe845,             0x3f4fb018,             0x078294bf,
295                 0x3ec00051,             0x3f6fac0f,             0x06b2b4bb,
296                 0x3ec0185f,             0x3f8fac07,             0x05e2ccb4,
297                 0x3ec0386b,             0x3fafac00,             0x0502e8ac,
298                 0x3ed05c77,             0x3fcfb3fb,             0x0432f0a3,
299                 0x3ef08482,             0x3fdfbbf6,             0x0372f898 },
300         },
301         { 0x2c00, {
302                 0x3eefdc31,             0x3eefdc31,             0x08e238b8,
303                 0x3edfec3d,             0x3f0fc828,             0x082258b9,
304                 0x3ed00049,             0x3f1fc01e,             0x077278b6,
305                 0x3ed01455,             0x3f3fb815,             0x06c294b2,
306                 0x3ed03460,             0x3f5fb40d,             0x0602acac,
307                 0x3ef0506c,             0x3f7fb006,             0x0542c0a4,
308                 0x3f107476,             0x3f9fb400,             0x0472c89d,
309                 0x3f309c80,             0x3fbfb7fc,             0x03b2cc94 },
310         },
311         { 0x2e00, {
312                 0x3eefec37,             0x3eefec37,             0x088220b0,
313                 0x3ee00041,             0x3effdc2d,             0x07f244ae,
314                 0x3ee0144c,             0x3f0fd023,             0x07625cad,
315                 0x3ef02c57,             0x3f1fc81a,             0x06c274a9,
316                 0x3f004861,             0x3f3fbc13,             0x060288a6,
317                 0x3f20686b,             0x3f5fb80c,             0x05529c9e,
318                 0x3f408c74,             0x3f6fb805,             0x04b2ac96,
319                 0x3f80ac7e,             0x3f8fb800,             0x0402ac8e },
320         },
321         { 0x3000, {
322                 0x3ef0003a,             0x3ef0003a,             0x084210a6,
323                 0x3ef01045,             0x3effec32,             0x07b228a7,
324                 0x3f00284e,             0x3f0fdc29,             0x073244a4,
325                 0x3f104058,             0x3f0fd420,             0x06a258a2,
326                 0x3f305c62,             0x3f2fc818,             0x0612689d,
327                 0x3f508069,             0x3f3fc011,             0x05728496,
328                 0x3f80a072,             0x3f4fc00a,             0x04d28c90,
329                 0x3fc0c07b,             0x3f6fbc04,             0x04429088 },
330         },
331         { 0x3200, {
332                 0x3f00103e,             0x3f00103e,             0x07f1fc9e,
333                 0x3f102447,             0x3f000035,             0x0782149d,
334                 0x3f203c4f,             0x3f0ff02c,             0x07122c9c,
335                 0x3f405458,             0x3f0fe424,             0x06924099,
336                 0x3f607061,             0x3f1fd41d,             0x06024c97,
337                 0x3f909068,             0x3f2fcc16,             0x05726490,
338                 0x3fc0b070,             0x3f3fc80f,             0x04f26c8a,
339                 0x0000d077,             0x3f4fc409,             0x04627484 },
340         },
341         { 0x3400, {
342                 0x3f202040,             0x3f202040,             0x07a1e898,
343                 0x3f303449,             0x3f100c38,             0x0741fc98,
344                 0x3f504c50,             0x3f10002f,             0x06e21495,
345                 0x3f706459,             0x3f1ff028,             0x06722492,
346                 0x3fa08060,             0x3f1fe421,             0x05f2348f,
347                 0x3fd09c67,             0x3f1fdc19,             0x05824c89,
348                 0x0000bc6e,             0x3f2fd014,             0x04f25086,
349                 0x0040dc74,             0x3f3fcc0d,             0x04825c7f },
350         },
351         { 0x3600, {
352                 0x3f403042,             0x3f403042,             0x0761d890,
353                 0x3f504848,             0x3f301c3b,             0x0701f090,
354                 0x3f805c50,             0x3f200c33,             0x06a2008f,
355                 0x3fa07458,             0x3f10002b,             0x06520c8d,
356                 0x3fd0905e,             0x3f1ff424,             0x05e22089,
357                 0x0000ac65,             0x3f1fe81d,             0x05823483,
358                 0x0030cc6a,             0x3f2fdc18,             0x04f23c81,
359                 0x0080e871,             0x3f2fd412,             0x0482407c },
360         },
361         { 0x3800, {
362                 0x3f604043,             0x3f604043,             0x0721c88a,
363                 0x3f80544a,             0x3f502c3c,             0x06d1d88a,
364                 0x3fb06851,             0x3f301c35,             0x0681e889,
365                 0x3fd08456,             0x3f30082f,             0x0611fc88,
366                 0x00009c5d,             0x3f200027,             0x05d20884,
367                 0x0030b863,             0x3f2ff421,             0x05621880,
368                 0x0070d468,             0x3f2fe81b,             0x0502247c,
369                 0x00c0ec6f,             0x3f2fe015,             0x04a22877 },
370         },
371         { 0x3a00, {
372                 0x3f904c44,             0x3f904c44,             0x06e1b884,
373                 0x3fb0604a,             0x3f70383e,             0x0691c885,
374                 0x3fe07451,             0x3f502c36,             0x0661d483,
375                 0x00009055,             0x3f401831,             0x0601ec81,
376                 0x0030a85b,             0x3f300c2a,             0x05b1f480,
377                 0x0070c061,             0x3f300024,             0x0562047a,
378                 0x00b0d867,             0x3f3ff41e,             0x05020c77,
379                 0x00f0f46b,             0x3f2fec19,             0x04a21474 },
380         },
381         { 0x3c00, {
382                 0x3fb05c43,             0x3fb05c43,             0x06c1b07e,
383                 0x3fe06c4b,             0x3f902c3f,             0x0681c081,
384                 0x0000844f,             0x3f703838,             0x0631cc7d,
385                 0x00309855,             0x3f602433,             0x05d1d47e,
386                 0x0060b459,             0x3f50142e,             0x0581e47b,
387                 0x00a0c85f,             0x3f400828,             0x0531f078,
388                 0x00e0e064,             0x3f300021,             0x0501fc73,
389                 0x00b0fc6a,             0x3f3ff41d,             0x04a20873 },
390         },
391         { 0x3e00, {
392                 0x3fe06444,             0x3fe06444,             0x0681a07a,
393                 0x00007849,             0x3fc0503f,             0x0641b07a,
394                 0x0020904d,             0x3fa0403a,             0x05f1c07a,
395                 0x0060a453,             0x3f803034,             0x05c1c878,
396                 0x0090b858,             0x3f70202f,             0x0571d477,
397                 0x00d0d05d,             0x3f501829,             0x0531e073,
398                 0x0110e462,             0x3f500825,             0x04e1e471,
399                 0x01510065,             0x3f40001f,             0x04a1f06d },
400         },
401         { 0x4000, {
402                 0x00007044,             0x00007044,             0x06519476,
403                 0x00208448,             0x3fe05c3f,             0x0621a476,
404                 0x0050984d,             0x3fc04c3a,             0x05e1b075,
405                 0x0080ac52,             0x3fa03c35,             0x05a1b875,
406                 0x00c0c056,             0x3f803030,             0x0561c473,
407                 0x0100d45b,             0x3f70202b,             0x0521d46f,
408                 0x0140e860,             0x3f601427,             0x04d1d46e,
409                 0x01810064,             0x3f500822,             0x0491dc6b },
410         },
411         { 0x5000, {
412                 0x0110a442,             0x0110a442,             0x0551545e,
413                 0x0140b045,             0x00e0983f,             0x0531585f,
414                 0x0160c047,             0x00c08c3c,             0x0511645e,
415                 0x0190cc4a,             0x00908039,             0x04f1685f,
416                 0x01c0dc4c,             0x00707436,             0x04d1705e,
417                 0x0200e850,             0x00506833,             0x04b1785b,
418                 0x0230f453,             0x00305c30,             0x0491805a,
419                 0x02710056,             0x0010542d,             0x04718059 },
420         },
421         { 0x6000, {
422                 0x01c0bc40,             0x01c0bc40,             0x04c13052,
423                 0x01e0c841,             0x01a0b43d,             0x04c13851,
424                 0x0210cc44,             0x0180a83c,             0x04a13453,
425                 0x0230d845,             0x0160a03a,             0x04913c52,
426                 0x0260e047,             0x01409838,             0x04714052,
427                 0x0280ec49,             0x01208c37,             0x04514c50,
428                 0x02b0f44b,             0x01008435,             0x04414c50,
429                 0x02d1004c,             0x00e07c33,             0x0431544f },
430         },
431         { 0x7000, {
432                 0x0230c83e,             0x0230c83e,             0x04711c4c,
433                 0x0250d03f,             0x0210c43c,             0x0471204b,
434                 0x0270d840,             0x0200b83c,             0x0451244b,
435                 0x0290dc42,             0x01e0b43a,             0x0441244c,
436                 0x02b0e443,             0x01c0b038,             0x0441284b,
437                 0x02d0ec44,             0x01b0a438,             0x0421304a,
438                 0x02f0f445,             0x0190a036,             0x04213449,
439                 0x0310f847,             0x01709c34,             0x04213848 },
440         },
441         { 0x8000, {
442                 0x0280d03d,             0x0280d03d,             0x04310c48,
443                 0x02a0d43e,             0x0270c83c,             0x04311047,
444                 0x02b0dc3e,             0x0250c83a,             0x04311447,
445                 0x02d0e040,             0x0240c03a,             0x04211446,
446                 0x02e0e840,             0x0220bc39,             0x04111847,
447                 0x0300e842,             0x0210b438,             0x04012445,
448                 0x0310f043,             0x0200b037,             0x04012045,
449                 0x0330f444,             0x01e0ac36,             0x03f12445 },
450         },
451         { 0xefff, {
452                 0x0340dc3a,             0x0340dc3a,             0x03b0ec40,
453                 0x0340e03a,             0x0330e039,             0x03c0f03e,
454                 0x0350e03b,             0x0330dc39,             0x03c0ec3e,
455                 0x0350e43a,             0x0320dc38,             0x03c0f43e,
456                 0x0360e43b,             0x0320d839,             0x03b0f03e,
457                 0x0360e83b,             0x0310d838,             0x03c0fc3b,
458                 0x0370e83b,             0x0310d439,             0x03a0f83d,
459                 0x0370e83c,             0x0300d438,             0x03b0fc3c },
460         }
461 };
462 
463 enum rcar_vin_state {
464         STOPPED = 0,
465         RUNNING,
466         STOPPING,
467 };
468 
469 struct rcar_vin_priv {
470         void __iomem                    *base;
471         spinlock_t                      lock;
472         int                             sequence;
473         /* State of the VIN module in capturing mode */
474         enum rcar_vin_state             state;
475         struct soc_camera_host          ici;
476         struct list_head                capture;
477 #define MAX_BUFFER_NUM                  3
478         struct vb2_buffer               *queue_buf[MAX_BUFFER_NUM];
479         struct vb2_alloc_ctx            *alloc_ctx;
480         enum v4l2_field                 field;
481         unsigned int                    pdata_flags;
482         unsigned int                    vb_count;
483         unsigned int                    nr_hw_slots;
484         bool                            request_to_stop;
485         struct completion               capture_stop;
486         enum chip_id                    chip;
487 };
488 
489 #define is_continuous_transfer(priv)    (priv->vb_count > MAX_BUFFER_NUM)
490 
491 struct rcar_vin_buffer {
492         struct vb2_buffer               vb;
493         struct list_head                list;
494 };
495 
496 #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
497                                                        struct rcar_vin_buffer, \
498                                                        vb)->list)
499 
500 struct rcar_vin_cam {
501         /* VIN offsets within the camera output, before the VIN scaler */
502         unsigned int                    vin_left;
503         unsigned int                    vin_top;
504         /* Client output, as seen by the VIN */
505         unsigned int                    width;
506         unsigned int                    height;
507         /* User window from S_FMT */
508         unsigned int out_width;
509         unsigned int out_height;
510         /*
511          * User window from S_CROP / G_CROP, produced by client cropping and
512          * scaling, VIN scaling and VIN cropping, mapped back onto the client
513          * input window
514          */
515         struct v4l2_rect                subrect;
516         /* Camera cropping rectangle */
517         struct v4l2_rect                rect;
518         const struct soc_mbus_pixelfmt  *extra_fmt;
519 };
520 
521 /*
522  * .queue_setup() is called to check whether the driver can accept the requested
523  * number of buffers and to fill in plane sizes for the current frame format if
524  * required
525  */
526 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
527                                    const struct v4l2_format *fmt,
528                                    unsigned int *count,
529                                    unsigned int *num_planes,
530                                    unsigned int sizes[], void *alloc_ctxs[])
531 {
532         struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
533         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
534         struct rcar_vin_priv *priv = ici->priv;
535 
536         if (fmt) {
537                 const struct soc_camera_format_xlate *xlate;
538                 unsigned int bytes_per_line;
539                 int ret;
540 
541                 xlate = soc_camera_xlate_by_fourcc(icd,
542                                                    fmt->fmt.pix.pixelformat);
543                 if (!xlate)
544                         return -EINVAL;
545                 ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
546                                               xlate->host_fmt);
547                 if (ret < 0)
548                         return ret;
549 
550                 bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret);
551 
552                 ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line,
553                                           fmt->fmt.pix.height);
554                 if (ret < 0)
555                         return ret;
556 
557                 sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret);
558         } else {
559                 /* Called from VIDIOC_REQBUFS or in compatibility mode */
560                 sizes[0] = icd->sizeimage;
561         }
562 
563         alloc_ctxs[0] = priv->alloc_ctx;
564 
565         if (!vq->num_buffers)
566                 priv->sequence = 0;
567 
568         if (!*count)
569                 *count = 2;
570         priv->vb_count = *count;
571 
572         *num_planes = 1;
573 
574         /* Number of hardware slots */
575         if (is_continuous_transfer(priv))
576                 priv->nr_hw_slots = MAX_BUFFER_NUM;
577         else
578                 priv->nr_hw_slots = 1;
579 
580         dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
581 
582         return 0;
583 }
584 
585 static int rcar_vin_setup(struct rcar_vin_priv *priv)
586 {
587         struct soc_camera_device *icd = priv->ici.icd;
588         struct rcar_vin_cam *cam = icd->host_priv;
589         u32 vnmc, dmr, interrupts;
590         bool progressive = false, output_is_yuv = false;
591 
592         switch (priv->field) {
593         case V4L2_FIELD_TOP:
594                 vnmc = VNMC_IM_ODD;
595                 break;
596         case V4L2_FIELD_BOTTOM:
597                 vnmc = VNMC_IM_EVEN;
598                 break;
599         case V4L2_FIELD_INTERLACED:
600         case V4L2_FIELD_INTERLACED_TB:
601                 vnmc = VNMC_IM_FULL;
602                 break;
603         case V4L2_FIELD_INTERLACED_BT:
604                 vnmc = VNMC_IM_FULL | VNMC_FOC;
605                 break;
606         case V4L2_FIELD_NONE:
607                 if (is_continuous_transfer(priv)) {
608                         vnmc = VNMC_IM_ODD_EVEN;
609                         progressive = true;
610                 } else {
611                         vnmc = VNMC_IM_ODD;
612                 }
613                 break;
614         default:
615                 vnmc = VNMC_IM_ODD;
616                 break;
617         }
618 
619         /* input interface */
620         switch (icd->current_fmt->code) {
621         case MEDIA_BUS_FMT_YUYV8_1X16:
622                 /* BT.601/BT.1358 16bit YCbCr422 */
623                 vnmc |= VNMC_INF_YUV16;
624                 break;
625         case MEDIA_BUS_FMT_YUYV8_2X8:
626                 /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
627                 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
628                         VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
629                 break;
630         case MEDIA_BUS_FMT_YUYV10_2X10:
631                 /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
632                 vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
633                         VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
634                 break;
635         default:
636                 break;
637         }
638 
639         /* output format */
640         switch (icd->current_fmt->host_fmt->fourcc) {
641         case V4L2_PIX_FMT_NV16:
642                 iowrite32(ALIGN(cam->width * cam->height, 0x80),
643                           priv->base + VNUVAOF_REG);
644                 dmr = VNDMR_DTMD_YCSEP;
645                 output_is_yuv = true;
646                 break;
647         case V4L2_PIX_FMT_YUYV:
648                 dmr = VNDMR_BPSM;
649                 output_is_yuv = true;
650                 break;
651         case V4L2_PIX_FMT_UYVY:
652                 dmr = 0;
653                 output_is_yuv = true;
654                 break;
655         case V4L2_PIX_FMT_RGB555X:
656                 dmr = VNDMR_DTMD_ARGB1555;
657                 break;
658         case V4L2_PIX_FMT_RGB565:
659                 dmr = 0;
660                 break;
661         case V4L2_PIX_FMT_RGB32:
662                 if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 ||
663                     priv->chip == RCAR_E1) {
664                         dmr = VNDMR_EXRGB;
665                         break;
666                 }
667         default:
668                 dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
669                          icd->current_fmt->host_fmt->fourcc);
670                 return -EINVAL;
671         }
672 
673         /* Always update on field change */
674         vnmc |= VNMC_VUP;
675 
676         /* If input and output use the same colorspace, use bypass mode */
677         if (output_is_yuv)
678                 vnmc |= VNMC_BPS;
679 
680         /* progressive or interlaced mode */
681         interrupts = progressive ? VNIE_FIE : VNIE_EFE;
682 
683         /* ack interrupts */
684         iowrite32(interrupts, priv->base + VNINTS_REG);
685         /* enable interrupts */
686         iowrite32(interrupts, priv->base + VNIE_REG);
687         /* start capturing */
688         iowrite32(dmr, priv->base + VNDMR_REG);
689         iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
690 
691         return 0;
692 }
693 
694 static void rcar_vin_capture(struct rcar_vin_priv *priv)
695 {
696         if (is_continuous_transfer(priv))
697                 /* Continuous Frame Capture Mode */
698                 iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
699         else
700                 /* Single Frame Capture Mode */
701                 iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
702 }
703 
704 static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
705 {
706         priv->state = STOPPING;
707 
708         /* set continuous & single transfer off */
709         iowrite32(0, priv->base + VNFC_REG);
710         /* disable capture (release DMA buffer), reset */
711         iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
712                   priv->base + VNMC_REG);
713 
714         /* update the status if stopped already */
715         if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
716                 priv->state = STOPPED;
717 }
718 
719 static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
720 {
721         int slot;
722 
723         for (slot = 0; slot < priv->nr_hw_slots; slot++)
724                 if (priv->queue_buf[slot] == NULL)
725                         return slot;
726 
727         return -1;
728 }
729 
730 static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
731 {
732         /* Ensure all HW slots are filled */
733         return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
734 }
735 
736 /* Moves a buffer from the queue to the HW slots */
737 static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
738 {
739         struct vb2_buffer *vb;
740         dma_addr_t phys_addr_top;
741         int slot;
742 
743         if (list_empty(&priv->capture))
744                 return 0;
745 
746         /* Find a free HW slot */
747         slot = rcar_vin_get_free_hw_slot(priv);
748         if (slot < 0)
749                 return 0;
750 
751         vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb;
752         list_del_init(to_buf_list(vb));
753         priv->queue_buf[slot] = vb;
754         phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0);
755         iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
756 
757         return 1;
758 }
759 
760 static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
761 {
762         struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
763         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
764         struct rcar_vin_priv *priv = ici->priv;
765         unsigned long size;
766 
767         size = icd->sizeimage;
768 
769         if (vb2_plane_size(vb, 0) < size) {
770                 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
771                         vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
772                 goto error;
773         }
774 
775         vb2_set_plane_payload(vb, 0, size);
776 
777         dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
778                 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
779 
780         spin_lock_irq(&priv->lock);
781 
782         list_add_tail(to_buf_list(vb), &priv->capture);
783         rcar_vin_fill_hw_slot(priv);
784 
785         /* If we weren't running, and have enough buffers, start capturing! */
786         if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
787                 if (rcar_vin_setup(priv)) {
788                         /* Submit error */
789                         list_del_init(to_buf_list(vb));
790                         spin_unlock_irq(&priv->lock);
791                         goto error;
792                 }
793                 priv->request_to_stop = false;
794                 init_completion(&priv->capture_stop);
795                 priv->state = RUNNING;
796                 rcar_vin_capture(priv);
797         }
798 
799         spin_unlock_irq(&priv->lock);
800 
801         return;
802 
803 error:
804         vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
805 }
806 
807 /*
808  * Wait for capture to stop and all in-flight buffers to be finished with by
809  * the video hardware. This must be called under &priv->lock
810  *
811  */
812 static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
813 {
814         while (priv->state != STOPPED) {
815                 /* issue stop if running */
816                 if (priv->state == RUNNING)
817                         rcar_vin_request_capture_stop(priv);
818 
819                 /* wait until capturing has been stopped */
820                 if (priv->state == STOPPING) {
821                         priv->request_to_stop = true;
822                         spin_unlock_irq(&priv->lock);
823                         wait_for_completion(&priv->capture_stop);
824                         spin_lock_irq(&priv->lock);
825                 }
826         }
827 }
828 
829 static void rcar_vin_stop_streaming(struct vb2_queue *vq)
830 {
831         struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
832         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
833         struct rcar_vin_priv *priv = ici->priv;
834         struct list_head *buf_head, *tmp;
835         int i;
836 
837         spin_lock_irq(&priv->lock);
838         rcar_vin_wait_stop_streaming(priv);
839 
840         for (i = 0; i < MAX_BUFFER_NUM; i++) {
841                 if (priv->queue_buf[i]) {
842                         vb2_buffer_done(priv->queue_buf[i],
843                                         VB2_BUF_STATE_ERROR);
844                         priv->queue_buf[i] = NULL;
845                 }
846         }
847 
848         list_for_each_safe(buf_head, tmp, &priv->capture) {
849                 vb2_buffer_done(&list_entry(buf_head,
850                                         struct rcar_vin_buffer, list)->vb,
851                                 VB2_BUF_STATE_ERROR);
852                 list_del_init(buf_head);
853         }
854         spin_unlock_irq(&priv->lock);
855 }
856 
857 static struct vb2_ops rcar_vin_vb2_ops = {
858         .queue_setup    = rcar_vin_videobuf_setup,
859         .buf_queue      = rcar_vin_videobuf_queue,
860         .stop_streaming = rcar_vin_stop_streaming,
861         .wait_prepare   = vb2_ops_wait_prepare,
862         .wait_finish    = vb2_ops_wait_finish,
863 };
864 
865 static irqreturn_t rcar_vin_irq(int irq, void *data)
866 {
867         struct rcar_vin_priv *priv = data;
868         u32 int_status;
869         bool can_run = false, hw_stopped;
870         int slot;
871         unsigned int handled = 0;
872 
873         spin_lock(&priv->lock);
874 
875         int_status = ioread32(priv->base + VNINTS_REG);
876         if (!int_status)
877                 goto done;
878         /* ack interrupts */
879         iowrite32(int_status, priv->base + VNINTS_REG);
880         handled = 1;
881 
882         /* nothing to do if capture status is 'STOPPED' */
883         if (priv->state == STOPPED)
884                 goto done;
885 
886         hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
887 
888         if (!priv->request_to_stop) {
889                 if (is_continuous_transfer(priv))
890                         slot = (ioread32(priv->base + VNMS_REG) &
891                                 VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
892                 else
893                         slot = 0;
894 
895                 priv->queue_buf[slot]->v4l2_buf.field = priv->field;
896                 priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++;
897                 do_gettimeofday(&priv->queue_buf[slot]->v4l2_buf.timestamp);
898                 vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE);
899                 priv->queue_buf[slot] = NULL;
900 
901                 if (priv->state != STOPPING)
902                         can_run = rcar_vin_fill_hw_slot(priv);
903 
904                 if (hw_stopped || !can_run) {
905                         priv->state = STOPPED;
906                 } else if (is_continuous_transfer(priv) &&
907                            list_empty(&priv->capture) &&
908                            priv->state == RUNNING) {
909                         /*
910                          * The continuous capturing requires an explicit stop
911                          * operation when there is no buffer to be set into
912                          * the VnMBm registers.
913                          */
914                         rcar_vin_request_capture_stop(priv);
915                 } else {
916                         rcar_vin_capture(priv);
917                 }
918 
919         } else if (hw_stopped) {
920                 priv->state = STOPPED;
921                 priv->request_to_stop = false;
922                 complete(&priv->capture_stop);
923         }
924 
925 done:
926         spin_unlock(&priv->lock);
927 
928         return IRQ_RETVAL(handled);
929 }
930 
931 static int rcar_vin_add_device(struct soc_camera_device *icd)
932 {
933         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
934         struct rcar_vin_priv *priv = ici->priv;
935         int i;
936 
937         for (i = 0; i < MAX_BUFFER_NUM; i++)
938                 priv->queue_buf[i] = NULL;
939 
940         pm_runtime_get_sync(ici->v4l2_dev.dev);
941 
942         dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
943                 icd->devnum);
944 
945         return 0;
946 }
947 
948 static void rcar_vin_remove_device(struct soc_camera_device *icd)
949 {
950         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
951         struct rcar_vin_priv *priv = ici->priv;
952         struct vb2_buffer *vb;
953         int i;
954 
955         /* disable capture, disable interrupts */
956         iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
957                   priv->base + VNMC_REG);
958         iowrite32(0, priv->base + VNIE_REG);
959 
960         priv->state = STOPPED;
961         priv->request_to_stop = false;
962 
963         /* make sure active buffer is cancelled */
964         spin_lock_irq(&priv->lock);
965         for (i = 0; i < MAX_BUFFER_NUM; i++) {
966                 vb = priv->queue_buf[i];
967                 if (vb) {
968                         list_del_init(to_buf_list(vb));
969                         vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
970                 }
971         }
972         spin_unlock_irq(&priv->lock);
973 
974         pm_runtime_put(ici->v4l2_dev.dev);
975 
976         dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
977                 icd->devnum);
978 }
979 
980 /* Called with .host_lock held */
981 static int rcar_vin_clock_start(struct soc_camera_host *ici)
982 {
983         /* VIN does not have "mclk" */
984         return 0;
985 }
986 
987 /* Called with .host_lock held */
988 static void rcar_vin_clock_stop(struct soc_camera_host *ici)
989 {
990         /* VIN does not have "mclk" */
991 }
992 
993 static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
994 {
995         int i;
996         const struct vin_coeff *p_prev_set = NULL;
997         const struct vin_coeff *p_set = NULL;
998 
999         /* Look for suitable coefficient values */
1000         for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
1001                 p_prev_set = p_set;
1002                 p_set = &vin_coeff_set[i];
1003 
1004                 if (xs < p_set->xs_value)
1005                         break;
1006         }
1007 
1008         /* Use previous value if its XS value is closer */
1009         if (p_prev_set && p_set &&
1010             xs - p_prev_set->xs_value < p_set->xs_value - xs)
1011                 p_set = p_prev_set;
1012 
1013         /* Set coefficient registers */
1014         iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
1015         iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
1016         iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
1017 
1018         iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
1019         iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
1020         iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
1021 
1022         iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
1023         iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
1024         iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
1025 
1026         iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
1027         iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
1028         iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
1029 
1030         iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
1031         iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
1032         iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
1033 
1034         iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
1035         iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
1036         iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
1037 
1038         iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
1039         iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
1040         iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
1041 
1042         iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
1043         iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
1044         iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
1045 }
1046 
1047 /* rect is guaranteed to not exceed the scaled camera rectangle */
1048 static int rcar_vin_set_rect(struct soc_camera_device *icd)
1049 {
1050         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1051         struct rcar_vin_cam *cam = icd->host_priv;
1052         struct rcar_vin_priv *priv = ici->priv;
1053         unsigned int left_offset, top_offset;
1054         unsigned char dsize = 0;
1055         struct v4l2_rect *cam_subrect = &cam->subrect;
1056         u32 value;
1057 
1058         dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
1059                 icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
1060 
1061         left_offset = cam->vin_left;
1062         top_offset = cam->vin_top;
1063 
1064         if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 &&
1065             priv->chip == RCAR_E1)
1066                 dsize = 1;
1067 
1068         dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
1069                 cam->width, cam->height, cam->vin_left, cam->vin_top);
1070         dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
1071                 cam_subrect->width, cam_subrect->height,
1072                 cam_subrect->left, cam_subrect->top);
1073 
1074         /* Set Start/End Pixel/Line Pre-Clip */
1075         iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
1076         iowrite32((left_offset + cam_subrect->width - 1) << dsize,
1077                   priv->base + VNEPPRC_REG);
1078         switch (priv->field) {
1079         case V4L2_FIELD_INTERLACED:
1080         case V4L2_FIELD_INTERLACED_TB:
1081         case V4L2_FIELD_INTERLACED_BT:
1082                 iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
1083                 iowrite32((top_offset + cam_subrect->height) / 2 - 1,
1084                           priv->base + VNELPRC_REG);
1085                 break;
1086         default:
1087                 iowrite32(top_offset, priv->base + VNSLPRC_REG);
1088                 iowrite32(top_offset + cam_subrect->height - 1,
1089                           priv->base + VNELPRC_REG);
1090                 break;
1091         }
1092 
1093         /* Set scaling coefficient */
1094         value = 0;
1095         if (cam_subrect->height != cam->out_height)
1096                 value = (4096 * cam_subrect->height) / cam->out_height;
1097         dev_dbg(icd->parent, "YS Value: %x\n", value);
1098         iowrite32(value, priv->base + VNYS_REG);
1099 
1100         value = 0;
1101         if (cam_subrect->width != cam->out_width)
1102                 value = (4096 * cam_subrect->width) / cam->out_width;
1103 
1104         /* Horizontal upscaling is up to double size */
1105         if (0 < value && value < 2048)
1106                 value = 2048;
1107 
1108         dev_dbg(icd->parent, "XS Value: %x\n", value);
1109         iowrite32(value, priv->base + VNXS_REG);
1110 
1111         /* Horizontal upscaling is carried out by scaling down from double size */
1112         if (value < 4096)
1113                 value *= 2;
1114 
1115         set_coeff(priv, value);
1116 
1117         /* Set Start/End Pixel/Line Post-Clip */
1118         iowrite32(0, priv->base + VNSPPOC_REG);
1119         iowrite32(0, priv->base + VNSLPOC_REG);
1120         iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
1121         switch (priv->field) {
1122         case V4L2_FIELD_INTERLACED:
1123         case V4L2_FIELD_INTERLACED_TB:
1124         case V4L2_FIELD_INTERLACED_BT:
1125                 iowrite32(cam->out_height / 2 - 1,
1126                           priv->base + VNELPOC_REG);
1127                 break;
1128         default:
1129                 iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
1130                 break;
1131         }
1132 
1133         iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
1134 
1135         return 0;
1136 }
1137 
1138 static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
1139 {
1140         *vnmc = ioread32(priv->base + VNMC_REG);
1141         /* module disable */
1142         iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
1143 }
1144 
1145 static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
1146 {
1147         unsigned long timeout = jiffies + 10 * HZ;
1148 
1149         /*
1150          * Wait until the end of the current frame. It can take a long time,
1151          * but if it has been aborted by a MRST1 reset, it should exit sooner.
1152          */
1153         while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
1154                 time_before(jiffies, timeout))
1155                 msleep(1);
1156 
1157         if (time_after(jiffies, timeout)) {
1158                 dev_err(priv->ici.v4l2_dev.dev,
1159                         "Timeout waiting for frame end! Interface problem?\n");
1160                 return;
1161         }
1162 
1163         iowrite32(vnmc, priv->base + VNMC_REG);
1164 }
1165 
1166 #define VIN_MBUS_FLAGS  (V4L2_MBUS_MASTER |             \
1167                          V4L2_MBUS_PCLK_SAMPLE_RISING | \
1168                          V4L2_MBUS_HSYNC_ACTIVE_HIGH |  \
1169                          V4L2_MBUS_HSYNC_ACTIVE_LOW |   \
1170                          V4L2_MBUS_VSYNC_ACTIVE_HIGH |  \
1171                          V4L2_MBUS_VSYNC_ACTIVE_LOW |   \
1172                          V4L2_MBUS_DATA_ACTIVE_HIGH)
1173 
1174 static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
1175 {
1176         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1177         struct rcar_vin_priv *priv = ici->priv;
1178         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1179         struct v4l2_mbus_config cfg;
1180         unsigned long common_flags;
1181         u32 vnmc;
1182         u32 val;
1183         int ret;
1184 
1185         capture_stop_preserve(priv, &vnmc);
1186 
1187         ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1188         if (!ret) {
1189                 common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1190                 if (!common_flags) {
1191                         dev_warn(icd->parent,
1192                                  "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1193                                  cfg.flags, VIN_MBUS_FLAGS);
1194                         return -EINVAL;
1195                 }
1196         } else if (ret != -ENOIOCTLCMD) {
1197                 return ret;
1198         } else {
1199                 common_flags = VIN_MBUS_FLAGS;
1200         }
1201 
1202         /* Make choises, based on platform preferences */
1203         if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1204             (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
1205                 if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
1206                         common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1207                 else
1208                         common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1209         }
1210 
1211         if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1212             (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
1213                 if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
1214                         common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1215                 else
1216                         common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1217         }
1218 
1219         cfg.flags = common_flags;
1220         ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1221         if (ret < 0 && ret != -ENOIOCTLCMD)
1222                 return ret;
1223 
1224         val = VNDMR2_FTEV | VNDMR2_VLV(1);
1225         if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
1226                 val |= VNDMR2_VPS;
1227         if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
1228                 val |= VNDMR2_HPS;
1229         iowrite32(val, priv->base + VNDMR2_REG);
1230 
1231         ret = rcar_vin_set_rect(icd);
1232         if (ret < 0)
1233                 return ret;
1234 
1235         capture_restore(priv, vnmc);
1236 
1237         return 0;
1238 }
1239 
1240 static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
1241                                   unsigned char buswidth)
1242 {
1243         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1244         struct v4l2_mbus_config cfg;
1245         int ret;
1246 
1247         ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1248         if (ret == -ENOIOCTLCMD)
1249                 return 0;
1250         else if (ret)
1251                 return ret;
1252 
1253         if (buswidth > 24)
1254                 return -EINVAL;
1255 
1256         /* check is there common mbus flags */
1257         ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
1258         if (ret)
1259                 return 0;
1260 
1261         dev_warn(icd->parent,
1262                 "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
1263                  cfg.flags, VIN_MBUS_FLAGS);
1264 
1265         return -EINVAL;
1266 }
1267 
1268 static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1269 {
1270         return  fmt->packing == SOC_MBUS_PACKING_NONE ||
1271                 (fmt->bits_per_sample > 8 &&
1272                  fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1273 }
1274 
1275 static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
1276         {
1277                 .fourcc                 = V4L2_PIX_FMT_NV16,
1278                 .name                   = "NV16",
1279                 .bits_per_sample        = 8,
1280                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
1281                 .order                  = SOC_MBUS_ORDER_LE,
1282                 .layout                 = SOC_MBUS_LAYOUT_PLANAR_Y_C,
1283         },
1284         {
1285                 .fourcc                 = V4L2_PIX_FMT_YUYV,
1286                 .name                   = "YUYV",
1287                 .bits_per_sample        = 16,
1288                 .packing                = SOC_MBUS_PACKING_NONE,
1289                 .order                  = SOC_MBUS_ORDER_LE,
1290                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
1291         },
1292         {
1293                 .fourcc                 = V4L2_PIX_FMT_UYVY,
1294                 .name                   = "UYVY",
1295                 .bits_per_sample        = 16,
1296                 .packing                = SOC_MBUS_PACKING_NONE,
1297                 .order                  = SOC_MBUS_ORDER_LE,
1298                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
1299         },
1300         {
1301                 .fourcc                 = V4L2_PIX_FMT_RGB565,
1302                 .name                   = "RGB565",
1303                 .bits_per_sample        = 16,
1304                 .packing                = SOC_MBUS_PACKING_NONE,
1305                 .order                  = SOC_MBUS_ORDER_LE,
1306                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
1307         },
1308         {
1309                 .fourcc                 = V4L2_PIX_FMT_RGB555X,
1310                 .name                   = "ARGB1555",
1311                 .bits_per_sample        = 16,
1312                 .packing                = SOC_MBUS_PACKING_NONE,
1313                 .order                  = SOC_MBUS_ORDER_LE,
1314                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
1315         },
1316         {
1317                 .fourcc                 = V4L2_PIX_FMT_RGB32,
1318                 .name                   = "RGB888",
1319                 .bits_per_sample        = 32,
1320                 .packing                = SOC_MBUS_PACKING_NONE,
1321                 .order                  = SOC_MBUS_ORDER_LE,
1322                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
1323         },
1324 };
1325 
1326 static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
1327                                 struct soc_camera_format_xlate *xlate)
1328 {
1329         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1330         struct device *dev = icd->parent;
1331         int ret, k, n;
1332         int formats = 0;
1333         struct rcar_vin_cam *cam;
1334         u32 code;
1335         const struct soc_mbus_pixelfmt *fmt;
1336 
1337         ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1338         if (ret < 0)
1339                 return 0;
1340 
1341         fmt = soc_mbus_get_fmtdesc(code);
1342         if (!fmt) {
1343                 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code);
1344                 return 0;
1345         }
1346 
1347         ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1348         if (ret < 0)
1349                 return 0;
1350 
1351         if (!icd->host_priv) {
1352                 struct v4l2_mbus_framefmt mf;
1353                 struct v4l2_rect rect;
1354                 struct device *dev = icd->parent;
1355                 int shift;
1356 
1357                 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1358                 if (ret < 0)
1359                         return ret;
1360 
1361                 /* Cache current client geometry */
1362                 ret = soc_camera_client_g_rect(sd, &rect);
1363                 if (ret == -ENOIOCTLCMD) {
1364                         /* Sensor driver doesn't support cropping */
1365                         rect.left = 0;
1366                         rect.top = 0;
1367                         rect.width = mf.width;
1368                         rect.height = mf.height;
1369                 } else if (ret < 0) {
1370                         return ret;
1371                 }
1372 
1373                 /*
1374                  * If sensor proposes too large format then try smaller ones:
1375                  * 1280x960, 640x480, 320x240
1376                  */
1377                 for (shift = 0; shift < 3; shift++) {
1378                         if (mf.width <= VIN_MAX_WIDTH &&
1379                             mf.height <= VIN_MAX_HEIGHT)
1380                                 break;
1381 
1382                         mf.width = 1280 >> shift;
1383                         mf.height = 960 >> shift;
1384                         ret = v4l2_device_call_until_err(sd->v4l2_dev,
1385                                                          soc_camera_grp_id(icd),
1386                                                          video, s_mbus_fmt,
1387                                                          &mf);
1388                         if (ret < 0)
1389                                 return ret;
1390                 }
1391 
1392                 if (shift == 3) {
1393                         dev_err(dev,
1394                                 "Failed to configure the client below %ux%u\n",
1395                                 mf.width, mf.height);
1396                         return -EIO;
1397                 }
1398 
1399                 dev_dbg(dev, "camera fmt %ux%u\n", mf.width, mf.height);
1400 
1401                 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1402                 if (!cam)
1403                         return -ENOMEM;
1404                 /*
1405                  * We are called with current camera crop,
1406                  * initialise subrect with it
1407                  */
1408                 cam->rect = rect;
1409                 cam->subrect = rect;
1410                 cam->width = mf.width;
1411                 cam->height = mf.height;
1412                 cam->out_width  = mf.width;
1413                 cam->out_height = mf.height;
1414 
1415                 icd->host_priv = cam;
1416         } else {
1417                 cam = icd->host_priv;
1418         }
1419 
1420         /* Beginning of a pass */
1421         if (!idx)
1422                 cam->extra_fmt = NULL;
1423 
1424         switch (code) {
1425         case MEDIA_BUS_FMT_YUYV8_1X16:
1426         case MEDIA_BUS_FMT_YUYV8_2X8:
1427         case MEDIA_BUS_FMT_YUYV10_2X10:
1428                 if (cam->extra_fmt)
1429                         break;
1430 
1431                 /* Add all our formats that can be generated by VIN */
1432                 cam->extra_fmt = rcar_vin_formats;
1433 
1434                 n = ARRAY_SIZE(rcar_vin_formats);
1435                 formats += n;
1436                 for (k = 0; xlate && k < n; k++, xlate++) {
1437                         xlate->host_fmt = &rcar_vin_formats[k];
1438                         xlate->code = code;
1439                         dev_dbg(dev, "Providing format %s using code %d\n",
1440                                 rcar_vin_formats[k].name, code);
1441                 }
1442                 break;
1443         default:
1444                 if (!rcar_vin_packing_supported(fmt))
1445                         return 0;
1446 
1447                 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1448                         fmt->name);
1449                 break;
1450         }
1451 
1452         /* Generic pass-through */
1453         formats++;
1454         if (xlate) {
1455                 xlate->host_fmt = fmt;
1456                 xlate->code = code;
1457                 xlate++;
1458         }
1459 
1460         return formats;
1461 }
1462 
1463 static void rcar_vin_put_formats(struct soc_camera_device *icd)
1464 {
1465         kfree(icd->host_priv);
1466         icd->host_priv = NULL;
1467 }
1468 
1469 static int rcar_vin_set_crop(struct soc_camera_device *icd,
1470                              const struct v4l2_crop *a)
1471 {
1472         struct v4l2_crop a_writable = *a;
1473         const struct v4l2_rect *rect = &a_writable.c;
1474         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1475         struct rcar_vin_priv *priv = ici->priv;
1476         struct v4l2_crop cam_crop;
1477         struct rcar_vin_cam *cam = icd->host_priv;
1478         struct v4l2_rect *cam_rect = &cam_crop.c;
1479         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1480         struct device *dev = icd->parent;
1481         struct v4l2_mbus_framefmt mf;
1482         u32 vnmc;
1483         int ret, i;
1484 
1485         dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
1486                 rect->left, rect->top);
1487 
1488         /* During camera cropping its output window can change too, stop VIN */
1489         capture_stop_preserve(priv, &vnmc);
1490         dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1491 
1492         /* Apply iterative camera S_CROP for new input window. */
1493         ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
1494                                        &cam->rect, &cam->subrect);
1495         if (ret < 0)
1496                 return ret;
1497 
1498         dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
1499                 cam_rect->width, cam_rect->height,
1500                 cam_rect->left, cam_rect->top);
1501 
1502         /* On success cam_crop contains current camera crop */
1503 
1504         /* Retrieve camera output window */
1505         ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1506         if (ret < 0)
1507                 return ret;
1508 
1509         if (mf.width > VIN_MAX_WIDTH || mf.height > VIN_MAX_HEIGHT)
1510                 return -EINVAL;
1511 
1512         /* Cache camera output window */
1513         cam->width = mf.width;
1514         cam->height = mf.height;
1515 
1516         icd->user_width  = cam->width;
1517         icd->user_height = cam->height;
1518 
1519         cam->vin_left = rect->left & ~1;
1520         cam->vin_top = rect->top & ~1;
1521 
1522         /* Use VIN cropping to crop to the new window. */
1523         ret = rcar_vin_set_rect(icd);
1524         if (ret < 0)
1525                 return ret;
1526 
1527         cam->subrect = *rect;
1528 
1529         dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
1530                 icd->user_width, icd->user_height,
1531                 cam->vin_left, cam->vin_top);
1532 
1533         /* Restore capture */
1534         for (i = 0; i < MAX_BUFFER_NUM; i++) {
1535                 if (priv->queue_buf[i] && priv->state == STOPPED) {
1536                         vnmc |= VNMC_ME;
1537                         break;
1538                 }
1539         }
1540         capture_restore(priv, vnmc);
1541 
1542         /* Even if only camera cropping succeeded */
1543         return ret;
1544 }
1545 
1546 static int rcar_vin_get_crop(struct soc_camera_device *icd,
1547                              struct v4l2_crop *a)
1548 {
1549         struct rcar_vin_cam *cam = icd->host_priv;
1550 
1551         a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1552         a->c = cam->subrect;
1553 
1554         return 0;
1555 }
1556 
1557 /* Similar to set_crop multistage iterative algorithm */
1558 static int rcar_vin_set_fmt(struct soc_camera_device *icd,
1559                             struct v4l2_format *f)
1560 {
1561         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1562         struct rcar_vin_priv *priv = ici->priv;
1563         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1564         struct rcar_vin_cam *cam = icd->host_priv;
1565         struct v4l2_pix_format *pix = &f->fmt.pix;
1566         struct v4l2_mbus_framefmt mf;
1567         struct device *dev = icd->parent;
1568         __u32 pixfmt = pix->pixelformat;
1569         const struct soc_camera_format_xlate *xlate;
1570         unsigned int vin_sub_width = 0, vin_sub_height = 0;
1571         int ret;
1572         bool can_scale;
1573         enum v4l2_field field;
1574         v4l2_std_id std;
1575 
1576         dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
1577                 pixfmt, pix->width, pix->height);
1578 
1579         switch (pix->field) {
1580         default:
1581                 pix->field = V4L2_FIELD_NONE;
1582                 /* fall-through */
1583         case V4L2_FIELD_NONE:
1584         case V4L2_FIELD_TOP:
1585         case V4L2_FIELD_BOTTOM:
1586         case V4L2_FIELD_INTERLACED_TB:
1587         case V4L2_FIELD_INTERLACED_BT:
1588                 field = pix->field;
1589                 break;
1590         case V4L2_FIELD_INTERLACED:
1591                 /* Query for standard if not explicitly mentioned _TB/_BT */
1592                 ret = v4l2_subdev_call(sd, video, querystd, &std);
1593                 if (ret < 0)
1594                         std = V4L2_STD_625_50;
1595 
1596                 field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB :
1597                                                 V4L2_FIELD_INTERLACED_BT;
1598                 break;
1599         }
1600 
1601         xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1602         if (!xlate) {
1603                 dev_warn(dev, "Format %x not found\n", pixfmt);
1604                 return -EINVAL;
1605         }
1606         /* Calculate client output geometry */
1607         soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1608                                       12);
1609         mf.field = pix->field;
1610         mf.colorspace = pix->colorspace;
1611         mf.code  = xlate->code;
1612 
1613         switch (pixfmt) {
1614         case V4L2_PIX_FMT_RGB32:
1615                 can_scale = priv->chip != RCAR_E1;
1616                 break;
1617         case V4L2_PIX_FMT_UYVY:
1618         case V4L2_PIX_FMT_YUYV:
1619         case V4L2_PIX_FMT_RGB565:
1620         case V4L2_PIX_FMT_RGB555X:
1621                 can_scale = true;
1622                 break;
1623         default:
1624                 can_scale = false;
1625                 break;
1626         }
1627 
1628         dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1629 
1630         ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1631                                       &mf, &vin_sub_width, &vin_sub_height,
1632                                       can_scale, 12);
1633 
1634         /* Done with the camera. Now see if we can improve the result */
1635         dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1636                 ret, mf.width, mf.height, pix->width, pix->height);
1637 
1638         if (ret == -ENOIOCTLCMD)
1639                 dev_dbg(dev, "Sensor doesn't support scaling\n");
1640         else if (ret < 0)
1641                 return ret;
1642 
1643         if (mf.code != xlate->code)
1644                 return -EINVAL;
1645 
1646         /* Prepare VIN crop */
1647         cam->width = mf.width;
1648         cam->height = mf.height;
1649 
1650         /* Use VIN scaling to scale to the requested user window. */
1651 
1652         /* We cannot scale up */
1653         if (pix->width > vin_sub_width)
1654                 vin_sub_width = pix->width;
1655 
1656         if (pix->height > vin_sub_height)
1657                 vin_sub_height = pix->height;
1658 
1659         pix->colorspace = mf.colorspace;
1660 
1661         if (!can_scale) {
1662                 pix->width = vin_sub_width;
1663                 pix->height = vin_sub_height;
1664         }
1665 
1666         /*
1667          * We have calculated CFLCR, the actual configuration will be performed
1668          * in rcar_vin_set_bus_param()
1669          */
1670 
1671         dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1672                 vin_sub_width, pix->width, vin_sub_height, pix->height);
1673 
1674         cam->out_width = pix->width;
1675         cam->out_height = pix->height;
1676 
1677         icd->current_fmt = xlate;
1678 
1679         priv->field = field;
1680 
1681         return 0;
1682 }
1683 
1684 static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1685                             struct v4l2_format *f)
1686 {
1687         const struct soc_camera_format_xlate *xlate;
1688         struct v4l2_pix_format *pix = &f->fmt.pix;
1689         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1690         struct v4l2_mbus_framefmt mf;
1691         __u32 pixfmt = pix->pixelformat;
1692         int width, height;
1693         int ret;
1694 
1695         xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1696         if (!xlate) {
1697                 xlate = icd->current_fmt;
1698                 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1699                         pixfmt, xlate->host_fmt->fourcc);
1700                 pixfmt = xlate->host_fmt->fourcc;
1701                 pix->pixelformat = pixfmt;
1702                 pix->colorspace = icd->colorspace;
1703         }
1704 
1705         /* FIXME: calculate using depth and bus width */
1706         v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1707                               &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1708 
1709         width = pix->width;
1710         height = pix->height;
1711 
1712         /* let soc-camera calculate these values */
1713         pix->bytesperline = 0;
1714         pix->sizeimage = 0;
1715 
1716         /* limit to sensor capabilities */
1717         mf.width = pix->width;
1718         mf.height = pix->height;
1719         mf.field = pix->field;
1720         mf.code = xlate->code;
1721         mf.colorspace = pix->colorspace;
1722 
1723         ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
1724                                          video, try_mbus_fmt, &mf);
1725         if (ret < 0)
1726                 return ret;
1727 
1728         /* Adjust only if VIN cannot scale */
1729         if (pix->width > mf.width * 2)
1730                 pix->width = mf.width * 2;
1731         if (pix->height > mf.height * 3)
1732                 pix->height = mf.height * 3;
1733 
1734         pix->field = mf.field;
1735         pix->colorspace = mf.colorspace;
1736 
1737         if (pixfmt == V4L2_PIX_FMT_NV16) {
1738                 /* FIXME: check against rect_max after converting soc-camera */
1739                 /* We can scale precisely, need a bigger image from camera */
1740                 if (pix->width < width || pix->height < height) {
1741                         /*
1742                          * We presume, the sensor behaves sanely, i.e. if
1743                          * requested a bigger rectangle, it will not return a
1744                          * smaller one.
1745                          */
1746                         mf.width = VIN_MAX_WIDTH;
1747                         mf.height = VIN_MAX_HEIGHT;
1748                         ret = v4l2_device_call_until_err(sd->v4l2_dev,
1749                                                          soc_camera_grp_id(icd),
1750                                                          video, try_mbus_fmt,
1751                                                          &mf);
1752                         if (ret < 0) {
1753                                 dev_err(icd->parent,
1754                                         "client try_fmt() = %d\n", ret);
1755                                 return ret;
1756                         }
1757                 }
1758                 /* We will scale exactly */
1759                 if (mf.width > width)
1760                         pix->width = width;
1761                 if (mf.height > height)
1762                         pix->height = height;
1763         }
1764 
1765         return ret;
1766 }
1767 
1768 static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1769 {
1770         struct soc_camera_device *icd = file->private_data;
1771 
1772         return vb2_poll(&icd->vb2_vidq, file, pt);
1773 }
1774 
1775 static int rcar_vin_querycap(struct soc_camera_host *ici,
1776                              struct v4l2_capability *cap)
1777 {
1778         strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
1779         cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1780         cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1781 
1782         return 0;
1783 }
1784 
1785 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1786                                    struct soc_camera_device *icd)
1787 {
1788         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1789 
1790         vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1791         vq->io_modes = VB2_MMAP | VB2_USERPTR;
1792         vq->drv_priv = icd;
1793         vq->ops = &rcar_vin_vb2_ops;
1794         vq->mem_ops = &vb2_dma_contig_memops;
1795         vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
1796         vq->timestamp_flags  = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1797         vq->lock = &ici->host_lock;
1798 
1799         return vb2_queue_init(vq);
1800 }
1801 
1802 static struct soc_camera_host_ops rcar_vin_host_ops = {
1803         .owner          = THIS_MODULE,
1804         .add            = rcar_vin_add_device,
1805         .remove         = rcar_vin_remove_device,
1806         .clock_start    = rcar_vin_clock_start,
1807         .clock_stop     = rcar_vin_clock_stop,
1808         .get_formats    = rcar_vin_get_formats,
1809         .put_formats    = rcar_vin_put_formats,
1810         .get_crop       = rcar_vin_get_crop,
1811         .set_crop       = rcar_vin_set_crop,
1812         .try_fmt        = rcar_vin_try_fmt,
1813         .set_fmt        = rcar_vin_set_fmt,
1814         .poll           = rcar_vin_poll,
1815         .querycap       = rcar_vin_querycap,
1816         .set_bus_param  = rcar_vin_set_bus_param,
1817         .init_videobuf2 = rcar_vin_init_videobuf2,
1818 };
1819 
1820 #ifdef CONFIG_OF
1821 static struct of_device_id rcar_vin_of_table[] = {
1822         { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1823         { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
1824         { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1825         { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1826         { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1827         { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1828         { },
1829 };
1830 MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1831 #endif
1832 
1833 static struct platform_device_id rcar_vin_id_table[] = {
1834         { "r8a7791-vin",  RCAR_GEN2 },
1835         { "r8a7790-vin",  RCAR_GEN2 },
1836         { "r8a7779-vin",  RCAR_H1 },
1837         { "r8a7778-vin",  RCAR_M1 },
1838         { "uPD35004-vin", RCAR_E1 },
1839         {},
1840 };
1841 MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
1842 
1843 static int rcar_vin_probe(struct platform_device *pdev)
1844 {
1845         const struct of_device_id *match = NULL;
1846         struct rcar_vin_priv *priv;
1847         struct resource *mem;
1848         struct rcar_vin_platform_data *pdata;
1849         unsigned int pdata_flags;
1850         int irq, ret;
1851 
1852         if (pdev->dev.of_node) {
1853                 struct v4l2_of_endpoint ep;
1854                 struct device_node *np;
1855 
1856                 match = of_match_device(of_match_ptr(rcar_vin_of_table),
1857                                         &pdev->dev);
1858 
1859                 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1860                 if (!np) {
1861                         dev_err(&pdev->dev, "could not find endpoint\n");
1862                         return -EINVAL;
1863                 }
1864 
1865                 ret = v4l2_of_parse_endpoint(np, &ep);
1866                 if (ret) {
1867                         dev_err(&pdev->dev, "could not parse endpoint\n");
1868                         return ret;
1869                 }
1870 
1871                 if (ep.bus_type == V4L2_MBUS_BT656)
1872                         pdata_flags = RCAR_VIN_BT656;
1873                 else {
1874                         pdata_flags = 0;
1875                         if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1876                                 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1877                         if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1878                                 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1879                 }
1880 
1881                 of_node_put(np);
1882 
1883                 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1884         } else {
1885                 pdata = pdev->dev.platform_data;
1886                 if (!pdata || !pdata->flags) {
1887                         dev_err(&pdev->dev, "platform data not set\n");
1888                         return -EINVAL;
1889                 }
1890                 pdata_flags = pdata->flags;
1891         }
1892 
1893         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1894         if (mem == NULL)
1895                 return -EINVAL;
1896 
1897         irq = platform_get_irq(pdev, 0);
1898         if (irq <= 0)
1899                 return -EINVAL;
1900 
1901         priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1902                             GFP_KERNEL);
1903         if (!priv)
1904                 return -ENOMEM;
1905 
1906         priv->base = devm_ioremap_resource(&pdev->dev, mem);
1907         if (IS_ERR(priv->base))
1908                 return PTR_ERR(priv->base);
1909 
1910         ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1911                                dev_name(&pdev->dev), priv);
1912         if (ret)
1913                 return ret;
1914 
1915         priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1916         if (IS_ERR(priv->alloc_ctx))
1917                 return PTR_ERR(priv->alloc_ctx);
1918 
1919         priv->ici.priv = priv;
1920         priv->ici.v4l2_dev.dev = &pdev->dev;
1921         priv->ici.drv_name = dev_name(&pdev->dev);
1922         priv->ici.ops = &rcar_vin_host_ops;
1923 
1924         priv->pdata_flags = pdata_flags;
1925         if (!match) {
1926                 priv->ici.nr = pdev->id;
1927                 priv->chip = pdev->id_entry->driver_data;
1928         } else {
1929                 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1930                 priv->chip = (enum chip_id)match->data;
1931         }
1932 
1933         spin_lock_init(&priv->lock);
1934         INIT_LIST_HEAD(&priv->capture);
1935 
1936         priv->state = STOPPED;
1937 
1938         pm_suspend_ignore_children(&pdev->dev, true);
1939         pm_runtime_enable(&pdev->dev);
1940 
1941         ret = soc_camera_host_register(&priv->ici);
1942         if (ret)
1943                 goto cleanup;
1944 
1945         return 0;
1946 
1947 cleanup:
1948         pm_runtime_disable(&pdev->dev);
1949         vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1950 
1951         return ret;
1952 }
1953 
1954 static int rcar_vin_remove(struct platform_device *pdev)
1955 {
1956         struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1957         struct rcar_vin_priv *priv = container_of(soc_host,
1958                                                   struct rcar_vin_priv, ici);
1959 
1960         soc_camera_host_unregister(soc_host);
1961         pm_runtime_disable(&pdev->dev);
1962         vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1963 
1964         return 0;
1965 }
1966 
1967 static struct platform_driver rcar_vin_driver = {
1968         .probe          = rcar_vin_probe,
1969         .remove         = rcar_vin_remove,
1970         .driver         = {
1971                 .name           = DRV_NAME,
1972                 .of_match_table = of_match_ptr(rcar_vin_of_table),
1973         },
1974         .id_table       = rcar_vin_id_table,
1975 };
1976 
1977 module_platform_driver(rcar_vin_driver);
1978 
1979 MODULE_LICENSE("GPL");
1980 MODULE_ALIAS("platform:rcar_vin");
1981 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
1982 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us