Version:  2.0.40 2.2.26 2.4.37 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 4.1

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

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