]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/video/soc_mediabus.c
Merge branch 'tip/perf/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/roste...
[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->layout != SOC_MBUS_LAYOUT_PACKED)
382                 return width * mf->bits_per_sample / 8;
383
384         switch (mf->packing) {
385         case SOC_MBUS_PACKING_NONE:
386                 return width * mf->bits_per_sample / 8;
387         case SOC_MBUS_PACKING_2X8_PADHI:
388         case SOC_MBUS_PACKING_2X8_PADLO:
389         case SOC_MBUS_PACKING_EXTEND16:
390                 return width * 2;
391         case SOC_MBUS_PACKING_1_5X8:
392                 return width * 3 / 2;
393         case SOC_MBUS_PACKING_VARIABLE:
394                 return 0;
395         }
396         return -EINVAL;
397 }
398 EXPORT_SYMBOL(soc_mbus_bytes_per_line);
399
400 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
401                         u32 bytes_per_line, u32 height)
402 {
403         if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
404                 return bytes_per_line * height;
405
406         switch (mf->packing) {
407         case SOC_MBUS_PACKING_2X8_PADHI:
408         case SOC_MBUS_PACKING_2X8_PADLO:
409                 return bytes_per_line * height * 2;
410         case SOC_MBUS_PACKING_1_5X8:
411                 return bytes_per_line * height * 3 / 2;
412         default:
413                 return -EINVAL;
414         }
415 }
416 EXPORT_SYMBOL(soc_mbus_image_size);
417
418 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
419         enum v4l2_mbus_pixelcode code,
420         const struct soc_mbus_lookup *lookup,
421         int n)
422 {
423         int i;
424
425         for (i = 0; i < n; i++)
426                 if (lookup[i].code == code)
427                         return &lookup[i].fmt;
428
429         return NULL;
430 }
431 EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
432
433 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
434         enum v4l2_mbus_pixelcode code)
435 {
436         return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
437 }
438 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
439
440 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
441                                         unsigned int flags)
442 {
443         unsigned long common_flags;
444         bool hsync = true, vsync = true, pclk, data, mode;
445         bool mipi_lanes, mipi_clock;
446
447         common_flags = cfg->flags & flags;
448
449         switch (cfg->type) {
450         case V4L2_MBUS_PARALLEL:
451                 hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
452                                         V4L2_MBUS_HSYNC_ACTIVE_LOW);
453                 vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
454                                         V4L2_MBUS_VSYNC_ACTIVE_LOW);
455         case V4L2_MBUS_BT656:
456                 pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
457                                        V4L2_MBUS_PCLK_SAMPLE_FALLING);
458                 data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
459                                        V4L2_MBUS_DATA_ACTIVE_LOW);
460                 mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
461                 return (!hsync || !vsync || !pclk || !data || !mode) ?
462                         0 : common_flags;
463         case V4L2_MBUS_CSI2:
464                 mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
465                 mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
466                                              V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
467                 return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
468         }
469         return 0;
470 }
471 EXPORT_SYMBOL(soc_mbus_config_compatible);
472
473 static int __init soc_mbus_init(void)
474 {
475         return 0;
476 }
477
478 static void __exit soc_mbus_exit(void)
479 {
480 }
481
482 module_init(soc_mbus_init);
483 module_exit(soc_mbus_exit);
484
485 MODULE_DESCRIPTION("soc-camera media bus interface");
486 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
487 MODULE_LICENSE("GPL v2");