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 4.5

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

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