]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/video/soc_mediabus.c
Merge tag 'nfs-for-3.6-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[karo-tx-linux.git] / drivers / media / video / soc_mediabus.c
1 /*
2  * soc-camera media bus helper routines
3  *
4  * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13
14 #include <media/v4l2-device.h>
15 #include <media/v4l2-mediabus.h>
16 #include <media/soc_mediabus.h>
17
18 static const struct soc_mbus_lookup mbus_fmt[] = {
19 {
20         .code = V4L2_MBUS_FMT_YUYV8_2X8,
21         .fmt = {
22                 .fourcc                 = V4L2_PIX_FMT_YUYV,
23                 .name                   = "YUYV",
24                 .bits_per_sample        = 8,
25                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
26                 .order                  = SOC_MBUS_ORDER_LE,
27                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
28         },
29 }, {
30         .code = V4L2_MBUS_FMT_YVYU8_2X8,
31         .fmt = {
32                 .fourcc                 = V4L2_PIX_FMT_YVYU,
33                 .name                   = "YVYU",
34                 .bits_per_sample        = 8,
35                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
36                 .order                  = SOC_MBUS_ORDER_LE,
37                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
38         },
39 }, {
40         .code = V4L2_MBUS_FMT_UYVY8_2X8,
41         .fmt = {
42                 .fourcc                 = V4L2_PIX_FMT_UYVY,
43                 .name                   = "UYVY",
44                 .bits_per_sample        = 8,
45                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
46                 .order                  = SOC_MBUS_ORDER_LE,
47                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
48         },
49 }, {
50         .code = V4L2_MBUS_FMT_VYUY8_2X8,
51         .fmt = {
52                 .fourcc                 = V4L2_PIX_FMT_VYUY,
53                 .name                   = "VYUY",
54                 .bits_per_sample        = 8,
55                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
56                 .order                  = SOC_MBUS_ORDER_LE,
57                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
58         },
59 }, {
60         .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
61         .fmt = {
62                 .fourcc                 = V4L2_PIX_FMT_RGB555,
63                 .name                   = "RGB555",
64                 .bits_per_sample        = 8,
65                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
66                 .order                  = SOC_MBUS_ORDER_LE,
67                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
68         },
69 }, {
70         .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
71         .fmt = {
72                 .fourcc                 = V4L2_PIX_FMT_RGB555X,
73                 .name                   = "RGB555X",
74                 .bits_per_sample        = 8,
75                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
76                 .order                  = SOC_MBUS_ORDER_LE,
77                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
78         },
79 }, {
80         .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
81         .fmt = {
82                 .fourcc                 = V4L2_PIX_FMT_RGB565,
83                 .name                   = "RGB565",
84                 .bits_per_sample        = 8,
85                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
86                 .order                  = SOC_MBUS_ORDER_LE,
87                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
88         },
89 }, {
90         .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
91         .fmt = {
92                 .fourcc                 = V4L2_PIX_FMT_RGB565X,
93                 .name                   = "RGB565X",
94                 .bits_per_sample        = 8,
95                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
96                 .order                  = SOC_MBUS_ORDER_LE,
97                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
98         },
99 }, {
100         .code = V4L2_MBUS_FMT_SBGGR8_1X8,
101         .fmt = {
102                 .fourcc                 = V4L2_PIX_FMT_SBGGR8,
103                 .name                   = "Bayer 8 BGGR",
104                 .bits_per_sample        = 8,
105                 .packing                = SOC_MBUS_PACKING_NONE,
106                 .order                  = SOC_MBUS_ORDER_LE,
107                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
108         },
109 }, {
110         .code = V4L2_MBUS_FMT_SBGGR10_1X10,
111         .fmt = {
112                 .fourcc                 = V4L2_PIX_FMT_SBGGR10,
113                 .name                   = "Bayer 10 BGGR",
114                 .bits_per_sample        = 10,
115                 .packing                = SOC_MBUS_PACKING_EXTEND16,
116                 .order                  = SOC_MBUS_ORDER_LE,
117                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
118         },
119 }, {
120         .code = V4L2_MBUS_FMT_Y8_1X8,
121         .fmt = {
122                 .fourcc                 = V4L2_PIX_FMT_GREY,
123                 .name                   = "Grey",
124                 .bits_per_sample        = 8,
125                 .packing                = SOC_MBUS_PACKING_NONE,
126                 .order                  = SOC_MBUS_ORDER_LE,
127                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
128         },
129 }, {
130         .code = V4L2_MBUS_FMT_Y10_1X10,
131         .fmt = {
132                 .fourcc                 = V4L2_PIX_FMT_Y10,
133                 .name                   = "Grey 10bit",
134                 .bits_per_sample        = 10,
135                 .packing                = SOC_MBUS_PACKING_EXTEND16,
136                 .order                  = SOC_MBUS_ORDER_LE,
137                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
138         },
139 }, {
140         .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
141         .fmt = {
142                 .fourcc                 = V4L2_PIX_FMT_SBGGR10,
143                 .name                   = "Bayer 10 BGGR",
144                 .bits_per_sample        = 8,
145                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
146                 .order                  = SOC_MBUS_ORDER_LE,
147                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
148         },
149 }, {
150         .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
151         .fmt = {
152                 .fourcc                 = V4L2_PIX_FMT_SBGGR10,
153                 .name                   = "Bayer 10 BGGR",
154                 .bits_per_sample        = 8,
155                 .packing                = SOC_MBUS_PACKING_2X8_PADLO,
156                 .order                  = SOC_MBUS_ORDER_LE,
157                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
158         },
159 }, {
160         .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
161         .fmt = {
162                 .fourcc                 = V4L2_PIX_FMT_SBGGR10,
163                 .name                   = "Bayer 10 BGGR",
164                 .bits_per_sample        = 8,
165                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
166                 .order                  = SOC_MBUS_ORDER_BE,
167                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
168         },
169 }, {
170         .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
171         .fmt = {
172                 .fourcc                 = V4L2_PIX_FMT_SBGGR10,
173                 .name                   = "Bayer 10 BGGR",
174                 .bits_per_sample        = 8,
175                 .packing                = SOC_MBUS_PACKING_2X8_PADLO,
176                 .order                  = SOC_MBUS_ORDER_BE,
177                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
178         },
179 }, {
180         .code = V4L2_MBUS_FMT_JPEG_1X8,
181         .fmt = {
182                 .fourcc                 = V4L2_PIX_FMT_JPEG,
183                 .name                   = "JPEG",
184                 .bits_per_sample        = 8,
185                 .packing                = SOC_MBUS_PACKING_VARIABLE,
186                 .order                  = SOC_MBUS_ORDER_LE,
187                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
188         },
189 }, {
190         .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
191         .fmt = {
192                 .fourcc                 = V4L2_PIX_FMT_RGB444,
193                 .name                   = "RGB444",
194                 .bits_per_sample        = 8,
195                 .packing                = SOC_MBUS_PACKING_2X8_PADHI,
196                 .order                  = SOC_MBUS_ORDER_BE,
197                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
198         },
199 }, {
200         .code = V4L2_MBUS_FMT_YUYV8_1_5X8,
201         .fmt = {
202                 .fourcc                 = V4L2_PIX_FMT_YUV420,
203                 .name                   = "YUYV 4:2:0",
204                 .bits_per_sample        = 8,
205                 .packing                = SOC_MBUS_PACKING_1_5X8,
206                 .order                  = SOC_MBUS_ORDER_LE,
207                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
208         },
209 }, {
210         .code = V4L2_MBUS_FMT_YVYU8_1_5X8,
211         .fmt = {
212                 .fourcc                 = V4L2_PIX_FMT_YVU420,
213                 .name                   = "YVYU 4:2:0",
214                 .bits_per_sample        = 8,
215                 .packing                = SOC_MBUS_PACKING_1_5X8,
216                 .order                  = SOC_MBUS_ORDER_LE,
217                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
218         },
219 }, {
220         .code = V4L2_MBUS_FMT_UYVY8_1X16,
221         .fmt = {
222                 .fourcc                 = V4L2_PIX_FMT_UYVY,
223                 .name                   = "UYVY 16bit",
224                 .bits_per_sample        = 16,
225                 .packing                = SOC_MBUS_PACKING_EXTEND16,
226                 .order                  = SOC_MBUS_ORDER_LE,
227                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
228         },
229 }, {
230         .code = V4L2_MBUS_FMT_VYUY8_1X16,
231         .fmt = {
232                 .fourcc                 = V4L2_PIX_FMT_VYUY,
233                 .name                   = "VYUY 16bit",
234                 .bits_per_sample        = 16,
235                 .packing                = SOC_MBUS_PACKING_EXTEND16,
236                 .order                  = SOC_MBUS_ORDER_LE,
237                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
238         },
239 }, {
240         .code = V4L2_MBUS_FMT_YUYV8_1X16,
241         .fmt = {
242                 .fourcc                 = V4L2_PIX_FMT_YUYV,
243                 .name                   = "YUYV 16bit",
244                 .bits_per_sample        = 16,
245                 .packing                = SOC_MBUS_PACKING_EXTEND16,
246                 .order                  = SOC_MBUS_ORDER_LE,
247                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
248         },
249 }, {
250         .code = V4L2_MBUS_FMT_YVYU8_1X16,
251         .fmt = {
252                 .fourcc                 = V4L2_PIX_FMT_YVYU,
253                 .name                   = "YVYU 16bit",
254                 .bits_per_sample        = 16,
255                 .packing                = SOC_MBUS_PACKING_EXTEND16,
256                 .order                  = SOC_MBUS_ORDER_LE,
257                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
258         },
259 }, {
260         .code = V4L2_MBUS_FMT_SGRBG8_1X8,
261         .fmt = {
262                 .fourcc                 = V4L2_PIX_FMT_SGRBG8,
263                 .name                   = "Bayer 8 GRBG",
264                 .bits_per_sample        = 8,
265                 .packing                = SOC_MBUS_PACKING_NONE,
266                 .order                  = SOC_MBUS_ORDER_LE,
267                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
268         },
269 }, {
270         .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
271         .fmt = {
272                 .fourcc                 = V4L2_PIX_FMT_SGRBG10DPCM8,
273                 .name                   = "Bayer 10 BGGR DPCM 8",
274                 .bits_per_sample        = 8,
275                 .packing                = SOC_MBUS_PACKING_NONE,
276                 .order                  = SOC_MBUS_ORDER_LE,
277                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
278         },
279 }, {
280         .code = V4L2_MBUS_FMT_SGBRG10_1X10,
281         .fmt = {
282                 .fourcc                 = V4L2_PIX_FMT_SGBRG10,
283                 .name                   = "Bayer 10 GBRG",
284                 .bits_per_sample        = 10,
285                 .packing                = SOC_MBUS_PACKING_EXTEND16,
286                 .order                  = SOC_MBUS_ORDER_LE,
287                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
288         },
289 }, {
290         .code = V4L2_MBUS_FMT_SGRBG10_1X10,
291         .fmt = {
292                 .fourcc                 = V4L2_PIX_FMT_SGRBG10,
293                 .name                   = "Bayer 10 GRBG",
294                 .bits_per_sample        = 10,
295                 .packing                = SOC_MBUS_PACKING_EXTEND16,
296                 .order                  = SOC_MBUS_ORDER_LE,
297                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
298         },
299 }, {
300         .code = V4L2_MBUS_FMT_SRGGB10_1X10,
301         .fmt = {
302                 .fourcc                 = V4L2_PIX_FMT_SRGGB10,
303                 .name                   = "Bayer 10 RGGB",
304                 .bits_per_sample        = 10,
305                 .packing                = SOC_MBUS_PACKING_EXTEND16,
306                 .order                  = SOC_MBUS_ORDER_LE,
307                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
308         },
309 }, {
310         .code = V4L2_MBUS_FMT_SBGGR12_1X12,
311         .fmt = {
312                 .fourcc                 = V4L2_PIX_FMT_SBGGR12,
313                 .name                   = "Bayer 12 BGGR",
314                 .bits_per_sample        = 12,
315                 .packing                = SOC_MBUS_PACKING_EXTEND16,
316                 .order                  = SOC_MBUS_ORDER_LE,
317                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
318         },
319 }, {
320         .code = V4L2_MBUS_FMT_SGBRG12_1X12,
321         .fmt = {
322                 .fourcc                 = V4L2_PIX_FMT_SGBRG12,
323                 .name                   = "Bayer 12 GBRG",
324                 .bits_per_sample        = 12,
325                 .packing                = SOC_MBUS_PACKING_EXTEND16,
326                 .order                  = SOC_MBUS_ORDER_LE,
327                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
328         },
329 }, {
330         .code = V4L2_MBUS_FMT_SGRBG12_1X12,
331         .fmt = {
332                 .fourcc                 = V4L2_PIX_FMT_SGRBG12,
333                 .name                   = "Bayer 12 GRBG",
334                 .bits_per_sample        = 12,
335                 .packing                = SOC_MBUS_PACKING_EXTEND16,
336                 .order                  = SOC_MBUS_ORDER_LE,
337                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
338         },
339 }, {
340         .code = V4L2_MBUS_FMT_SRGGB12_1X12,
341         .fmt = {
342                 .fourcc                 = V4L2_PIX_FMT_SRGGB12,
343                 .name                   = "Bayer 12 RGGB",
344                 .bits_per_sample        = 12,
345                 .packing                = SOC_MBUS_PACKING_EXTEND16,
346                 .order                  = SOC_MBUS_ORDER_LE,
347                 .layout                 = SOC_MBUS_LAYOUT_PACKED,
348         },
349 },
350 };
351
352 int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
353                         unsigned int *numerator, unsigned int *denominator)
354 {
355         switch (mf->packing) {
356         case SOC_MBUS_PACKING_NONE:
357         case SOC_MBUS_PACKING_EXTEND16:
358                 *numerator = 1;
359                 *denominator = 1;
360                 return 0;
361         case SOC_MBUS_PACKING_2X8_PADHI:
362         case SOC_MBUS_PACKING_2X8_PADLO:
363                 *numerator = 2;
364                 *denominator = 1;
365                 return 0;
366         case SOC_MBUS_PACKING_1_5X8:
367                 *numerator = 3;
368                 *denominator = 2;
369                 return 0;
370         case SOC_MBUS_PACKING_VARIABLE:
371                 *numerator = 0;
372                 *denominator = 1;
373                 return 0;
374         }
375         return -EINVAL;
376 }
377 EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
378
379 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
380 {
381         if (mf->fourcc == V4L2_PIX_FMT_JPEG)
382                 return 0;
383
384         if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
385                 return width * mf->bits_per_sample / 8;
386
387         switch (mf->packing) {
388         case SOC_MBUS_PACKING_NONE:
389                 return width * mf->bits_per_sample / 8;
390         case SOC_MBUS_PACKING_2X8_PADHI:
391         case SOC_MBUS_PACKING_2X8_PADLO:
392         case SOC_MBUS_PACKING_EXTEND16:
393                 return width * 2;
394         case SOC_MBUS_PACKING_1_5X8:
395                 return width * 3 / 2;
396         case SOC_MBUS_PACKING_VARIABLE:
397                 return 0;
398         }
399         return -EINVAL;
400 }
401 EXPORT_SYMBOL(soc_mbus_bytes_per_line);
402
403 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
404                         u32 bytes_per_line, u32 height)
405 {
406         if (mf->fourcc == V4L2_PIX_FMT_JPEG)
407                 return 0;
408
409         if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
410                 return bytes_per_line * height;
411
412         switch (mf->packing) {
413         case SOC_MBUS_PACKING_2X8_PADHI:
414         case SOC_MBUS_PACKING_2X8_PADLO:
415                 return bytes_per_line * height * 2;
416         case SOC_MBUS_PACKING_1_5X8:
417                 return bytes_per_line * height * 3 / 2;
418         default:
419                 return -EINVAL;
420         }
421 }
422 EXPORT_SYMBOL(soc_mbus_image_size);
423
424 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
425         enum v4l2_mbus_pixelcode code,
426         const struct soc_mbus_lookup *lookup,
427         int n)
428 {
429         int i;
430
431         for (i = 0; i < n; i++)
432                 if (lookup[i].code == code)
433                         return &lookup[i].fmt;
434
435         return NULL;
436 }
437 EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
438
439 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
440         enum v4l2_mbus_pixelcode code)
441 {
442         return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
443 }
444 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
445
446 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
447                                         unsigned int flags)
448 {
449         unsigned long common_flags;
450         bool hsync = true, vsync = true, pclk, data, mode;
451         bool mipi_lanes, mipi_clock;
452
453         common_flags = cfg->flags & flags;
454
455         switch (cfg->type) {
456         case V4L2_MBUS_PARALLEL:
457                 hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
458                                         V4L2_MBUS_HSYNC_ACTIVE_LOW);
459                 vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
460                                         V4L2_MBUS_VSYNC_ACTIVE_LOW);
461         case V4L2_MBUS_BT656:
462                 pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
463                                        V4L2_MBUS_PCLK_SAMPLE_FALLING);
464                 data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
465                                        V4L2_MBUS_DATA_ACTIVE_LOW);
466                 mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
467                 return (!hsync || !vsync || !pclk || !data || !mode) ?
468                         0 : common_flags;
469         case V4L2_MBUS_CSI2:
470                 mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
471                 mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
472                                              V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
473                 return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
474         }
475         return 0;
476 }
477 EXPORT_SYMBOL(soc_mbus_config_compatible);
478
479 static int __init soc_mbus_init(void)
480 {
481         return 0;
482 }
483
484 static void __exit soc_mbus_exit(void)
485 {
486 }
487
488 module_init(soc_mbus_init);
489 module_exit(soc_mbus_exit);
490
491 MODULE_DESCRIPTION("soc-camera media bus interface");
492 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
493 MODULE_LICENSE("GPL v2");