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

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                 v4l2_get_timestamp(&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         struct v4l2_subdev_mbus_code_enum code = {
1327                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1328                 .index = idx,
1329         };
1330         const struct soc_mbus_pixelfmt *fmt;
1331 
1332         ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
1333         if (ret < 0)
1334                 return 0;
1335 
1336         fmt = soc_mbus_get_fmtdesc(code.code);
1337         if (!fmt) {
1338                 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
1339                 return 0;
1340         }
1341 
1342         ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
1343         if (ret < 0)
1344                 return 0;
1345 
1346         if (!icd->host_priv) {
1347                 struct v4l2_subdev_format fmt = {
1348                         .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1349                 };
1350                 struct v4l2_mbus_framefmt *mf = &fmt.format;
1351                 struct v4l2_rect rect;
1352                 struct device *dev = icd->parent;
1353                 int shift;
1354 
1355                 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1356                 if (ret < 0)
1357                         return ret;
1358 
1359                 /* Cache current client geometry */
1360                 ret = soc_camera_client_g_rect(sd, &rect);
1361                 if (ret == -ENOIOCTLCMD) {
1362                         /* Sensor driver doesn't support cropping */
1363                         rect.left = 0;
1364                         rect.top = 0;
1365                         rect.width = mf->width;
1366                         rect.height = mf->height;
1367                 } else if (ret < 0) {
1368                         return ret;
1369                 }
1370 
1371                 /*
1372                  * If sensor proposes too large format then try smaller ones:
1373                  * 1280x960, 640x480, 320x240
1374                  */
1375                 for (shift = 0; shift < 3; shift++) {
1376                         if (mf->width <= VIN_MAX_WIDTH &&
1377                             mf->height <= VIN_MAX_HEIGHT)
1378                                 break;
1379 
1380                         mf->width = 1280 >> shift;
1381                         mf->height = 960 >> shift;
1382                         ret = v4l2_device_call_until_err(sd->v4l2_dev,
1383                                                          soc_camera_grp_id(icd),
1384                                                          pad, set_fmt, NULL,
1385                                                          &fmt);
1386                         if (ret < 0)
1387                                 return ret;
1388                 }
1389 
1390                 if (shift == 3) {
1391                         dev_err(dev,
1392                                 "Failed to configure the client below %ux%u\n",
1393                                 mf->width, mf->height);
1394                         return -EIO;
1395                 }
1396 
1397                 dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
1398 
1399                 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1400                 if (!cam)
1401                         return -ENOMEM;
1402                 /*
1403                  * We are called with current camera crop,
1404                  * initialise subrect with it
1405                  */
1406                 cam->rect = rect;
1407                 cam->subrect = rect;
1408                 cam->width = mf->width;
1409                 cam->height = mf->height;
1410                 cam->out_width  = mf->width;
1411                 cam->out_height = mf->height;
1412 
1413                 icd->host_priv = cam;
1414         } else {
1415                 cam = icd->host_priv;
1416         }
1417 
1418         /* Beginning of a pass */
1419         if (!idx)
1420                 cam->extra_fmt = NULL;
1421 
1422         switch (code.code) {
1423         case MEDIA_BUS_FMT_YUYV8_1X16:
1424         case MEDIA_BUS_FMT_YUYV8_2X8:
1425         case MEDIA_BUS_FMT_YUYV10_2X10:
1426                 if (cam->extra_fmt)
1427                         break;
1428 
1429                 /* Add all our formats that can be generated by VIN */
1430                 cam->extra_fmt = rcar_vin_formats;
1431 
1432                 n = ARRAY_SIZE(rcar_vin_formats);
1433                 formats += n;
1434                 for (k = 0; xlate && k < n; k++, xlate++) {
1435                         xlate->host_fmt = &rcar_vin_formats[k];
1436                         xlate->code = code.code;
1437                         dev_dbg(dev, "Providing format %s using code %d\n",
1438                                 rcar_vin_formats[k].name, code.code);
1439                 }
1440                 break;
1441         default:
1442                 if (!rcar_vin_packing_supported(fmt))
1443                         return 0;
1444 
1445                 dev_dbg(dev, "Providing format %s in pass-through mode\n",
1446                         fmt->name);
1447                 break;
1448         }
1449 
1450         /* Generic pass-through */
1451         formats++;
1452         if (xlate) {
1453                 xlate->host_fmt = fmt;
1454                 xlate->code = code.code;
1455                 xlate++;
1456         }
1457 
1458         return formats;
1459 }
1460 
1461 static void rcar_vin_put_formats(struct soc_camera_device *icd)
1462 {
1463         kfree(icd->host_priv);
1464         icd->host_priv = NULL;
1465 }
1466 
1467 static int rcar_vin_set_crop(struct soc_camera_device *icd,
1468                              const struct v4l2_crop *a)
1469 {
1470         struct v4l2_crop a_writable = *a;
1471         const struct v4l2_rect *rect = &a_writable.c;
1472         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1473         struct rcar_vin_priv *priv = ici->priv;
1474         struct v4l2_crop cam_crop;
1475         struct rcar_vin_cam *cam = icd->host_priv;
1476         struct v4l2_rect *cam_rect = &cam_crop.c;
1477         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1478         struct device *dev = icd->parent;
1479         struct v4l2_subdev_format fmt = {
1480                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1481         };
1482         struct v4l2_mbus_framefmt *mf = &fmt.format;
1483         u32 vnmc;
1484         int ret, i;
1485 
1486         dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
1487                 rect->left, rect->top);
1488 
1489         /* During camera cropping its output window can change too, stop VIN */
1490         capture_stop_preserve(priv, &vnmc);
1491         dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1492 
1493         /* Apply iterative camera S_CROP for new input window. */
1494         ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
1495                                        &cam->rect, &cam->subrect);
1496         if (ret < 0)
1497                 return ret;
1498 
1499         dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
1500                 cam_rect->width, cam_rect->height,
1501                 cam_rect->left, cam_rect->top);
1502 
1503         /* On success cam_crop contains current camera crop */
1504 
1505         /* Retrieve camera output window */
1506         ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1507         if (ret < 0)
1508                 return ret;
1509 
1510         if (mf->width > VIN_MAX_WIDTH || mf->height > VIN_MAX_HEIGHT)
1511                 return -EINVAL;
1512 
1513         /* Cache camera output window */
1514         cam->width = mf->width;
1515         cam->height = mf->height;
1516 
1517         icd->user_width  = cam->width;
1518         icd->user_height = cam->height;
1519 
1520         cam->vin_left = rect->left & ~1;
1521         cam->vin_top = rect->top & ~1;
1522 
1523         /* Use VIN cropping to crop to the new window. */
1524         ret = rcar_vin_set_rect(icd);
1525         if (ret < 0)
1526                 return ret;
1527 
1528         cam->subrect = *rect;
1529 
1530         dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
1531                 icd->user_width, icd->user_height,
1532                 cam->vin_left, cam->vin_top);
1533 
1534         /* Restore capture */
1535         for (i = 0; i < MAX_BUFFER_NUM; i++) {
1536                 if (priv->queue_buf[i] && priv->state == STOPPED) {
1537                         vnmc |= VNMC_ME;
1538                         break;
1539                 }
1540         }
1541         capture_restore(priv, vnmc);
1542 
1543         /* Even if only camera cropping succeeded */
1544         return ret;
1545 }
1546 
1547 static int rcar_vin_get_crop(struct soc_camera_device *icd,
1548                              struct v4l2_crop *a)
1549 {
1550         struct rcar_vin_cam *cam = icd->host_priv;
1551 
1552         a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1553         a->c = cam->subrect;
1554 
1555         return 0;
1556 }
1557 
1558 /* Similar to set_crop multistage iterative algorithm */
1559 static int rcar_vin_set_fmt(struct soc_camera_device *icd,
1560                             struct v4l2_format *f)
1561 {
1562         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1563         struct rcar_vin_priv *priv = ici->priv;
1564         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1565         struct rcar_vin_cam *cam = icd->host_priv;
1566         struct v4l2_pix_format *pix = &f->fmt.pix;
1567         struct v4l2_mbus_framefmt mf;
1568         struct device *dev = icd->parent;
1569         __u32 pixfmt = pix->pixelformat;
1570         const struct soc_camera_format_xlate *xlate;
1571         unsigned int vin_sub_width = 0, vin_sub_height = 0;
1572         int ret;
1573         bool can_scale;
1574         enum v4l2_field field;
1575         v4l2_std_id std;
1576 
1577         dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
1578                 pixfmt, pix->width, pix->height);
1579 
1580         switch (pix->field) {
1581         default:
1582                 pix->field = V4L2_FIELD_NONE;
1583                 /* fall-through */
1584         case V4L2_FIELD_NONE:
1585         case V4L2_FIELD_TOP:
1586         case V4L2_FIELD_BOTTOM:
1587         case V4L2_FIELD_INTERLACED_TB:
1588         case V4L2_FIELD_INTERLACED_BT:
1589                 field = pix->field;
1590                 break;
1591         case V4L2_FIELD_INTERLACED:
1592                 /* Query for standard if not explicitly mentioned _TB/_BT */
1593                 ret = v4l2_subdev_call(sd, video, querystd, &std);
1594                 if (ret < 0)
1595                         std = V4L2_STD_625_50;
1596 
1597                 field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB :
1598                                                 V4L2_FIELD_INTERLACED_BT;
1599                 break;
1600         }
1601 
1602         xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1603         if (!xlate) {
1604                 dev_warn(dev, "Format %x not found\n", pixfmt);
1605                 return -EINVAL;
1606         }
1607         /* Calculate client output geometry */
1608         soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
1609                                       12);
1610         mf.field = pix->field;
1611         mf.colorspace = pix->colorspace;
1612         mf.code  = xlate->code;
1613 
1614         switch (pixfmt) {
1615         case V4L2_PIX_FMT_RGB32:
1616                 can_scale = priv->chip != RCAR_E1;
1617                 break;
1618         case V4L2_PIX_FMT_UYVY:
1619         case V4L2_PIX_FMT_YUYV:
1620         case V4L2_PIX_FMT_RGB565:
1621         case V4L2_PIX_FMT_RGB555X:
1622                 can_scale = true;
1623                 break;
1624         default:
1625                 can_scale = false;
1626                 break;
1627         }
1628 
1629         dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
1630 
1631         ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
1632                                       &mf, &vin_sub_width, &vin_sub_height,
1633                                       can_scale, 12);
1634 
1635         /* Done with the camera. Now see if we can improve the result */
1636         dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1637                 ret, mf.width, mf.height, pix->width, pix->height);
1638 
1639         if (ret == -ENOIOCTLCMD)
1640                 dev_dbg(dev, "Sensor doesn't support scaling\n");
1641         else if (ret < 0)
1642                 return ret;
1643 
1644         if (mf.code != xlate->code)
1645                 return -EINVAL;
1646 
1647         /* Prepare VIN crop */
1648         cam->width = mf.width;
1649         cam->height = mf.height;
1650 
1651         /* Use VIN scaling to scale to the requested user window. */
1652 
1653         /* We cannot scale up */
1654         if (pix->width > vin_sub_width)
1655                 vin_sub_width = pix->width;
1656 
1657         if (pix->height > vin_sub_height)
1658                 vin_sub_height = pix->height;
1659 
1660         pix->colorspace = mf.colorspace;
1661 
1662         if (!can_scale) {
1663                 pix->width = vin_sub_width;
1664                 pix->height = vin_sub_height;
1665         }
1666 
1667         /*
1668          * We have calculated CFLCR, the actual configuration will be performed
1669          * in rcar_vin_set_bus_param()
1670          */
1671 
1672         dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
1673                 vin_sub_width, pix->width, vin_sub_height, pix->height);
1674 
1675         cam->out_width = pix->width;
1676         cam->out_height = pix->height;
1677 
1678         icd->current_fmt = xlate;
1679 
1680         priv->field = field;
1681 
1682         return 0;
1683 }
1684 
1685 static int rcar_vin_try_fmt(struct soc_camera_device *icd,
1686                             struct v4l2_format *f)
1687 {
1688         const struct soc_camera_format_xlate *xlate;
1689         struct v4l2_pix_format *pix = &f->fmt.pix;
1690         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1691         struct v4l2_subdev_pad_config pad_cfg;
1692         struct v4l2_subdev_format format = {
1693                 .which = V4L2_SUBDEV_FORMAT_TRY,
1694         };
1695         struct v4l2_mbus_framefmt *mf = &format.format;
1696         __u32 pixfmt = pix->pixelformat;
1697         int width, height;
1698         int ret;
1699 
1700         xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1701         if (!xlate) {
1702                 xlate = icd->current_fmt;
1703                 dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
1704                         pixfmt, xlate->host_fmt->fourcc);
1705                 pixfmt = xlate->host_fmt->fourcc;
1706                 pix->pixelformat = pixfmt;
1707                 pix->colorspace = icd->colorspace;
1708         }
1709 
1710         /* FIXME: calculate using depth and bus width */
1711         v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
1712                               &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
1713 
1714         width = pix->width;
1715         height = pix->height;
1716 
1717         /* let soc-camera calculate these values */
1718         pix->bytesperline = 0;
1719         pix->sizeimage = 0;
1720 
1721         /* limit to sensor capabilities */
1722         mf->width = pix->width;
1723         mf->height = pix->height;
1724         mf->field = pix->field;
1725         mf->code = xlate->code;
1726         mf->colorspace = pix->colorspace;
1727 
1728         ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
1729                                          pad, set_fmt, &pad_cfg, &format);
1730         if (ret < 0)
1731                 return ret;
1732 
1733         /* Adjust only if VIN cannot scale */
1734         if (pix->width > mf->width * 2)
1735                 pix->width = mf->width * 2;
1736         if (pix->height > mf->height * 3)
1737                 pix->height = mf->height * 3;
1738 
1739         pix->field = mf->field;
1740         pix->colorspace = mf->colorspace;
1741 
1742         if (pixfmt == V4L2_PIX_FMT_NV16) {
1743                 /* FIXME: check against rect_max after converting soc-camera */
1744                 /* We can scale precisely, need a bigger image from camera */
1745                 if (pix->width < width || pix->height < height) {
1746                         /*
1747                          * We presume, the sensor behaves sanely, i.e. if
1748                          * requested a bigger rectangle, it will not return a
1749                          * smaller one.
1750                          */
1751                         mf->width = VIN_MAX_WIDTH;
1752                         mf->height = VIN_MAX_HEIGHT;
1753                         ret = v4l2_device_call_until_err(sd->v4l2_dev,
1754                                                          soc_camera_grp_id(icd),
1755                                                          pad, set_fmt, &pad_cfg,
1756                                                          &format);
1757                         if (ret < 0) {
1758                                 dev_err(icd->parent,
1759                                         "client try_fmt() = %d\n", ret);
1760                                 return ret;
1761                         }
1762                 }
1763                 /* We will scale exactly */
1764                 if (mf->width > width)
1765                         pix->width = width;
1766                 if (mf->height > height)
1767                         pix->height = height;
1768         }
1769 
1770         return ret;
1771 }
1772 
1773 static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
1774 {
1775         struct soc_camera_device *icd = file->private_data;
1776 
1777         return vb2_poll(&icd->vb2_vidq, file, pt);
1778 }
1779 
1780 static int rcar_vin_querycap(struct soc_camera_host *ici,
1781                              struct v4l2_capability *cap)
1782 {
1783         strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
1784         cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1785         cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1786 
1787         return 0;
1788 }
1789 
1790 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
1791                                    struct soc_camera_device *icd)
1792 {
1793         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1794 
1795         vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1796         vq->io_modes = VB2_MMAP | VB2_USERPTR;
1797         vq->drv_priv = icd;
1798         vq->ops = &rcar_vin_vb2_ops;
1799         vq->mem_ops = &vb2_dma_contig_memops;
1800         vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
1801         vq->timestamp_flags  = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1802         vq->lock = &ici->host_lock;
1803 
1804         return vb2_queue_init(vq);
1805 }
1806 
1807 static struct soc_camera_host_ops rcar_vin_host_ops = {
1808         .owner          = THIS_MODULE,
1809         .add            = rcar_vin_add_device,
1810         .remove         = rcar_vin_remove_device,
1811         .get_formats    = rcar_vin_get_formats,
1812         .put_formats    = rcar_vin_put_formats,
1813         .get_crop       = rcar_vin_get_crop,
1814         .set_crop       = rcar_vin_set_crop,
1815         .try_fmt        = rcar_vin_try_fmt,
1816         .set_fmt        = rcar_vin_set_fmt,
1817         .poll           = rcar_vin_poll,
1818         .querycap       = rcar_vin_querycap,
1819         .set_bus_param  = rcar_vin_set_bus_param,
1820         .init_videobuf2 = rcar_vin_init_videobuf2,
1821 };
1822 
1823 #ifdef CONFIG_OF
1824 static const struct of_device_id rcar_vin_of_table[] = {
1825         { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
1826         { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
1827         { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
1828         { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1829         { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1830         { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1831         { },
1832 };
1833 MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
1834 #endif
1835 
1836 static struct platform_device_id rcar_vin_id_table[] = {
1837         { "r8a7791-vin",  RCAR_GEN2 },
1838         { "r8a7790-vin",  RCAR_GEN2 },
1839         { "r8a7779-vin",  RCAR_H1 },
1840         { "r8a7778-vin",  RCAR_M1 },
1841         { "uPD35004-vin", RCAR_E1 },
1842         {},
1843 };
1844 MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
1845 
1846 static int rcar_vin_probe(struct platform_device *pdev)
1847 {
1848         const struct of_device_id *match = NULL;
1849         struct rcar_vin_priv *priv;
1850         struct resource *mem;
1851         struct rcar_vin_platform_data *pdata;
1852         unsigned int pdata_flags;
1853         int irq, ret;
1854 
1855         if (pdev->dev.of_node) {
1856                 struct v4l2_of_endpoint ep;
1857                 struct device_node *np;
1858 
1859                 match = of_match_device(of_match_ptr(rcar_vin_of_table),
1860                                         &pdev->dev);
1861 
1862                 np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
1863                 if (!np) {
1864                         dev_err(&pdev->dev, "could not find endpoint\n");
1865                         return -EINVAL;
1866                 }
1867 
1868                 ret = v4l2_of_parse_endpoint(np, &ep);
1869                 if (ret) {
1870                         dev_err(&pdev->dev, "could not parse endpoint\n");
1871                         return ret;
1872                 }
1873 
1874                 if (ep.bus_type == V4L2_MBUS_BT656)
1875                         pdata_flags = RCAR_VIN_BT656;
1876                 else {
1877                         pdata_flags = 0;
1878                         if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1879                                 pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
1880                         if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1881                                 pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
1882                 }
1883 
1884                 of_node_put(np);
1885 
1886                 dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
1887         } else {
1888                 pdata = pdev->dev.platform_data;
1889                 if (!pdata || !pdata->flags) {
1890                         dev_err(&pdev->dev, "platform data not set\n");
1891                         return -EINVAL;
1892                 }
1893                 pdata_flags = pdata->flags;
1894         }
1895 
1896         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1897         if (mem == NULL)
1898                 return -EINVAL;
1899 
1900         irq = platform_get_irq(pdev, 0);
1901         if (irq <= 0)
1902                 return -EINVAL;
1903 
1904         priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
1905                             GFP_KERNEL);
1906         if (!priv)
1907                 return -ENOMEM;
1908 
1909         priv->base = devm_ioremap_resource(&pdev->dev, mem);
1910         if (IS_ERR(priv->base))
1911                 return PTR_ERR(priv->base);
1912 
1913         ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
1914                                dev_name(&pdev->dev), priv);
1915         if (ret)
1916                 return ret;
1917 
1918         priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1919         if (IS_ERR(priv->alloc_ctx))
1920                 return PTR_ERR(priv->alloc_ctx);
1921 
1922         priv->ici.priv = priv;
1923         priv->ici.v4l2_dev.dev = &pdev->dev;
1924         priv->ici.drv_name = dev_name(&pdev->dev);
1925         priv->ici.ops = &rcar_vin_host_ops;
1926 
1927         priv->pdata_flags = pdata_flags;
1928         if (!match) {
1929                 priv->ici.nr = pdev->id;
1930                 priv->chip = pdev->id_entry->driver_data;
1931         } else {
1932                 priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
1933                 priv->chip = (enum chip_id)match->data;
1934         }
1935 
1936         spin_lock_init(&priv->lock);
1937         INIT_LIST_HEAD(&priv->capture);
1938 
1939         priv->state = STOPPED;
1940 
1941         pm_suspend_ignore_children(&pdev->dev, true);
1942         pm_runtime_enable(&pdev->dev);
1943 
1944         ret = soc_camera_host_register(&priv->ici);
1945         if (ret)
1946                 goto cleanup;
1947 
1948         return 0;
1949 
1950 cleanup:
1951         pm_runtime_disable(&pdev->dev);
1952         vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1953 
1954         return ret;
1955 }
1956 
1957 static int rcar_vin_remove(struct platform_device *pdev)
1958 {
1959         struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1960         struct rcar_vin_priv *priv = container_of(soc_host,
1961                                                   struct rcar_vin_priv, ici);
1962 
1963         soc_camera_host_unregister(soc_host);
1964         pm_runtime_disable(&pdev->dev);
1965         vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
1966 
1967         return 0;
1968 }
1969 
1970 static struct platform_driver rcar_vin_driver = {
1971         .probe          = rcar_vin_probe,
1972         .remove         = rcar_vin_remove,
1973         .driver         = {
1974                 .name           = DRV_NAME,
1975                 .of_match_table = of_match_ptr(rcar_vin_of_table),
1976         },
1977         .id_table       = rcar_vin_id_table,
1978 };
1979 
1980 module_platform_driver(rcar_vin_driver);
1981 
1982 MODULE_LICENSE("GPL");
1983 MODULE_ALIAS("platform:rcar_vin");
1984 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
1985 

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