Version:  2.0.40 2.2.26 2.4.37 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 4.2 4.3 4.4

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

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