2 * soc-camera media bus helper routines
4 * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
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.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
14 #include <media/v4l2-device.h>
15 #include <media/v4l2-mediabus.h>
16 #include <media/soc_mediabus.h>
18 static const struct soc_mbus_lookup mbus_fmt
[] = {
20 .code
= V4L2_MBUS_FMT_YUYV8_2X8
,
22 .fourcc
= V4L2_PIX_FMT_YUYV
,
25 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
26 .order
= SOC_MBUS_ORDER_LE
,
27 .layout
= SOC_MBUS_LAYOUT_PACKED
,
30 .code
= V4L2_MBUS_FMT_YVYU8_2X8
,
32 .fourcc
= V4L2_PIX_FMT_YVYU
,
35 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
36 .order
= SOC_MBUS_ORDER_LE
,
37 .layout
= SOC_MBUS_LAYOUT_PACKED
,
40 .code
= V4L2_MBUS_FMT_UYVY8_2X8
,
42 .fourcc
= V4L2_PIX_FMT_UYVY
,
45 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
46 .order
= SOC_MBUS_ORDER_LE
,
47 .layout
= SOC_MBUS_LAYOUT_PACKED
,
50 .code
= V4L2_MBUS_FMT_VYUY8_2X8
,
52 .fourcc
= V4L2_PIX_FMT_VYUY
,
55 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
56 .order
= SOC_MBUS_ORDER_LE
,
57 .layout
= SOC_MBUS_LAYOUT_PACKED
,
60 .code
= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE
,
62 .fourcc
= V4L2_PIX_FMT_RGB555
,
65 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
66 .order
= SOC_MBUS_ORDER_LE
,
67 .layout
= SOC_MBUS_LAYOUT_PACKED
,
70 .code
= V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE
,
72 .fourcc
= V4L2_PIX_FMT_RGB555X
,
75 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
76 .order
= SOC_MBUS_ORDER_BE
,
77 .layout
= SOC_MBUS_LAYOUT_PACKED
,
80 .code
= V4L2_MBUS_FMT_RGB565_2X8_LE
,
82 .fourcc
= V4L2_PIX_FMT_RGB565
,
85 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
86 .order
= SOC_MBUS_ORDER_LE
,
87 .layout
= SOC_MBUS_LAYOUT_PACKED
,
90 .code
= V4L2_MBUS_FMT_RGB565_2X8_BE
,
92 .fourcc
= V4L2_PIX_FMT_RGB565X
,
95 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
96 .order
= SOC_MBUS_ORDER_BE
,
97 .layout
= SOC_MBUS_LAYOUT_PACKED
,
100 .code
= V4L2_MBUS_FMT_RGB666_1X18
,
102 .fourcc
= V4L2_PIX_FMT_RGB32
,
103 .name
= "RGB666/32bpp",
104 .bits_per_sample
= 18,
105 .packing
= SOC_MBUS_PACKING_EXTEND32
,
106 .order
= SOC_MBUS_ORDER_LE
,
109 .code
= V4L2_MBUS_FMT_RGB888_1X24
,
111 .fourcc
= V4L2_PIX_FMT_RGB32
,
112 .name
= "RGB888/32bpp",
113 .bits_per_sample
= 24,
114 .packing
= SOC_MBUS_PACKING_EXTEND32
,
115 .order
= SOC_MBUS_ORDER_LE
,
118 .code
= V4L2_MBUS_FMT_RGB888_2X12_BE
,
120 .fourcc
= V4L2_PIX_FMT_RGB32
,
121 .name
= "RGB888/32bpp",
122 .bits_per_sample
= 12,
123 .packing
= SOC_MBUS_PACKING_EXTEND32
,
124 .order
= SOC_MBUS_ORDER_BE
,
127 .code
= V4L2_MBUS_FMT_RGB888_2X12_LE
,
129 .fourcc
= V4L2_PIX_FMT_RGB32
,
130 .name
= "RGB888/32bpp",
131 .bits_per_sample
= 12,
132 .packing
= SOC_MBUS_PACKING_EXTEND32
,
133 .order
= SOC_MBUS_ORDER_LE
,
136 .code
= V4L2_MBUS_FMT_SBGGR8_1X8
,
138 .fourcc
= V4L2_PIX_FMT_SBGGR8
,
139 .name
= "Bayer 8 BGGR",
140 .bits_per_sample
= 8,
141 .packing
= SOC_MBUS_PACKING_NONE
,
142 .order
= SOC_MBUS_ORDER_LE
,
143 .layout
= SOC_MBUS_LAYOUT_PACKED
,
146 .code
= V4L2_MBUS_FMT_SBGGR10_1X10
,
148 .fourcc
= V4L2_PIX_FMT_SBGGR10
,
149 .name
= "Bayer 10 BGGR",
150 .bits_per_sample
= 10,
151 .packing
= SOC_MBUS_PACKING_EXTEND16
,
152 .order
= SOC_MBUS_ORDER_LE
,
153 .layout
= SOC_MBUS_LAYOUT_PACKED
,
156 .code
= V4L2_MBUS_FMT_Y8_1X8
,
158 .fourcc
= V4L2_PIX_FMT_GREY
,
160 .bits_per_sample
= 8,
161 .packing
= SOC_MBUS_PACKING_NONE
,
162 .order
= SOC_MBUS_ORDER_LE
,
163 .layout
= SOC_MBUS_LAYOUT_PACKED
,
166 .code
= V4L2_MBUS_FMT_Y10_1X10
,
168 .fourcc
= V4L2_PIX_FMT_Y10
,
169 .name
= "Grey 10bit",
170 .bits_per_sample
= 10,
171 .packing
= SOC_MBUS_PACKING_EXTEND16
,
172 .order
= SOC_MBUS_ORDER_LE
,
173 .layout
= SOC_MBUS_LAYOUT_PACKED
,
176 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE
,
178 .fourcc
= V4L2_PIX_FMT_SBGGR10
,
179 .name
= "Bayer 10 BGGR",
180 .bits_per_sample
= 8,
181 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
182 .order
= SOC_MBUS_ORDER_LE
,
183 .layout
= SOC_MBUS_LAYOUT_PACKED
,
186 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE
,
188 .fourcc
= V4L2_PIX_FMT_SBGGR10
,
189 .name
= "Bayer 10 BGGR",
190 .bits_per_sample
= 8,
191 .packing
= SOC_MBUS_PACKING_2X8_PADLO
,
192 .order
= SOC_MBUS_ORDER_LE
,
193 .layout
= SOC_MBUS_LAYOUT_PACKED
,
196 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE
,
198 .fourcc
= V4L2_PIX_FMT_SBGGR10
,
199 .name
= "Bayer 10 BGGR",
200 .bits_per_sample
= 8,
201 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
202 .order
= SOC_MBUS_ORDER_BE
,
203 .layout
= SOC_MBUS_LAYOUT_PACKED
,
206 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE
,
208 .fourcc
= V4L2_PIX_FMT_SBGGR10
,
209 .name
= "Bayer 10 BGGR",
210 .bits_per_sample
= 8,
211 .packing
= SOC_MBUS_PACKING_2X8_PADLO
,
212 .order
= SOC_MBUS_ORDER_BE
,
213 .layout
= SOC_MBUS_LAYOUT_PACKED
,
216 .code
= V4L2_MBUS_FMT_JPEG_1X8
,
218 .fourcc
= V4L2_PIX_FMT_JPEG
,
220 .bits_per_sample
= 8,
221 .packing
= SOC_MBUS_PACKING_VARIABLE
,
222 .order
= SOC_MBUS_ORDER_LE
,
223 .layout
= SOC_MBUS_LAYOUT_PACKED
,
226 .code
= V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE
,
228 .fourcc
= V4L2_PIX_FMT_RGB444
,
230 .bits_per_sample
= 8,
231 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
232 .order
= SOC_MBUS_ORDER_BE
,
233 .layout
= SOC_MBUS_LAYOUT_PACKED
,
236 .code
= V4L2_MBUS_FMT_YUYV8_1_5X8
,
238 .fourcc
= V4L2_PIX_FMT_YUV420
,
239 .name
= "YUYV 4:2:0",
240 .bits_per_sample
= 8,
241 .packing
= SOC_MBUS_PACKING_1_5X8
,
242 .order
= SOC_MBUS_ORDER_LE
,
243 .layout
= SOC_MBUS_LAYOUT_PACKED
,
246 .code
= V4L2_MBUS_FMT_YVYU8_1_5X8
,
248 .fourcc
= V4L2_PIX_FMT_YVU420
,
249 .name
= "YVYU 4:2:0",
250 .bits_per_sample
= 8,
251 .packing
= SOC_MBUS_PACKING_1_5X8
,
252 .order
= SOC_MBUS_ORDER_LE
,
253 .layout
= SOC_MBUS_LAYOUT_PACKED
,
256 .code
= V4L2_MBUS_FMT_UYVY8_1X16
,
258 .fourcc
= V4L2_PIX_FMT_UYVY
,
259 .name
= "UYVY 16bit",
260 .bits_per_sample
= 16,
261 .packing
= SOC_MBUS_PACKING_EXTEND16
,
262 .order
= SOC_MBUS_ORDER_LE
,
263 .layout
= SOC_MBUS_LAYOUT_PACKED
,
266 .code
= V4L2_MBUS_FMT_VYUY8_1X16
,
268 .fourcc
= V4L2_PIX_FMT_VYUY
,
269 .name
= "VYUY 16bit",
270 .bits_per_sample
= 16,
271 .packing
= SOC_MBUS_PACKING_EXTEND16
,
272 .order
= SOC_MBUS_ORDER_LE
,
273 .layout
= SOC_MBUS_LAYOUT_PACKED
,
276 .code
= V4L2_MBUS_FMT_YUYV8_1X16
,
278 .fourcc
= V4L2_PIX_FMT_YUYV
,
279 .name
= "YUYV 16bit",
280 .bits_per_sample
= 16,
281 .packing
= SOC_MBUS_PACKING_EXTEND16
,
282 .order
= SOC_MBUS_ORDER_LE
,
283 .layout
= SOC_MBUS_LAYOUT_PACKED
,
286 .code
= V4L2_MBUS_FMT_YVYU8_1X16
,
288 .fourcc
= V4L2_PIX_FMT_YVYU
,
289 .name
= "YVYU 16bit",
290 .bits_per_sample
= 16,
291 .packing
= SOC_MBUS_PACKING_EXTEND16
,
292 .order
= SOC_MBUS_ORDER_LE
,
293 .layout
= SOC_MBUS_LAYOUT_PACKED
,
296 .code
= V4L2_MBUS_FMT_SGRBG8_1X8
,
298 .fourcc
= V4L2_PIX_FMT_SGRBG8
,
299 .name
= "Bayer 8 GRBG",
300 .bits_per_sample
= 8,
301 .packing
= SOC_MBUS_PACKING_NONE
,
302 .order
= SOC_MBUS_ORDER_LE
,
303 .layout
= SOC_MBUS_LAYOUT_PACKED
,
306 .code
= V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8
,
308 .fourcc
= V4L2_PIX_FMT_SGRBG10DPCM8
,
309 .name
= "Bayer 10 BGGR DPCM 8",
310 .bits_per_sample
= 8,
311 .packing
= SOC_MBUS_PACKING_NONE
,
312 .order
= SOC_MBUS_ORDER_LE
,
313 .layout
= SOC_MBUS_LAYOUT_PACKED
,
316 .code
= V4L2_MBUS_FMT_SGBRG10_1X10
,
318 .fourcc
= V4L2_PIX_FMT_SGBRG10
,
319 .name
= "Bayer 10 GBRG",
320 .bits_per_sample
= 10,
321 .packing
= SOC_MBUS_PACKING_EXTEND16
,
322 .order
= SOC_MBUS_ORDER_LE
,
323 .layout
= SOC_MBUS_LAYOUT_PACKED
,
326 .code
= V4L2_MBUS_FMT_SGRBG10_1X10
,
328 .fourcc
= V4L2_PIX_FMT_SGRBG10
,
329 .name
= "Bayer 10 GRBG",
330 .bits_per_sample
= 10,
331 .packing
= SOC_MBUS_PACKING_EXTEND16
,
332 .order
= SOC_MBUS_ORDER_LE
,
333 .layout
= SOC_MBUS_LAYOUT_PACKED
,
336 .code
= V4L2_MBUS_FMT_SRGGB10_1X10
,
338 .fourcc
= V4L2_PIX_FMT_SRGGB10
,
339 .name
= "Bayer 10 RGGB",
340 .bits_per_sample
= 10,
341 .packing
= SOC_MBUS_PACKING_EXTEND16
,
342 .order
= SOC_MBUS_ORDER_LE
,
343 .layout
= SOC_MBUS_LAYOUT_PACKED
,
346 .code
= V4L2_MBUS_FMT_SBGGR12_1X12
,
348 .fourcc
= V4L2_PIX_FMT_SBGGR12
,
349 .name
= "Bayer 12 BGGR",
350 .bits_per_sample
= 12,
351 .packing
= SOC_MBUS_PACKING_EXTEND16
,
352 .order
= SOC_MBUS_ORDER_LE
,
353 .layout
= SOC_MBUS_LAYOUT_PACKED
,
356 .code
= V4L2_MBUS_FMT_SGBRG12_1X12
,
358 .fourcc
= V4L2_PIX_FMT_SGBRG12
,
359 .name
= "Bayer 12 GBRG",
360 .bits_per_sample
= 12,
361 .packing
= SOC_MBUS_PACKING_EXTEND16
,
362 .order
= SOC_MBUS_ORDER_LE
,
363 .layout
= SOC_MBUS_LAYOUT_PACKED
,
366 .code
= V4L2_MBUS_FMT_SGRBG12_1X12
,
368 .fourcc
= V4L2_PIX_FMT_SGRBG12
,
369 .name
= "Bayer 12 GRBG",
370 .bits_per_sample
= 12,
371 .packing
= SOC_MBUS_PACKING_EXTEND16
,
372 .order
= SOC_MBUS_ORDER_LE
,
373 .layout
= SOC_MBUS_LAYOUT_PACKED
,
376 .code
= V4L2_MBUS_FMT_SRGGB12_1X12
,
378 .fourcc
= V4L2_PIX_FMT_SRGGB12
,
379 .name
= "Bayer 12 RGGB",
380 .bits_per_sample
= 12,
381 .packing
= SOC_MBUS_PACKING_EXTEND16
,
382 .order
= SOC_MBUS_ORDER_LE
,
383 .layout
= SOC_MBUS_LAYOUT_PACKED
,
388 int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt
*mf
,
389 unsigned int *numerator
, unsigned int *denominator
)
391 switch (mf
->packing
) {
392 case SOC_MBUS_PACKING_NONE
:
393 case SOC_MBUS_PACKING_EXTEND16
:
397 case SOC_MBUS_PACKING_EXTEND32
:
401 case SOC_MBUS_PACKING_2X8_PADHI
:
402 case SOC_MBUS_PACKING_2X8_PADLO
:
406 case SOC_MBUS_PACKING_1_5X8
:
410 case SOC_MBUS_PACKING_VARIABLE
:
417 EXPORT_SYMBOL(soc_mbus_samples_per_pixel
);
419 s32
soc_mbus_bytes_per_line(u32 width
, const struct soc_mbus_pixelfmt
*mf
)
421 if (mf
->layout
!= SOC_MBUS_LAYOUT_PACKED
)
422 return width
* mf
->bits_per_sample
/ 8;
424 switch (mf
->packing
) {
425 case SOC_MBUS_PACKING_NONE
:
426 return width
* mf
->bits_per_sample
/ 8;
427 case SOC_MBUS_PACKING_2X8_PADHI
:
428 case SOC_MBUS_PACKING_2X8_PADLO
:
429 case SOC_MBUS_PACKING_EXTEND16
:
431 case SOC_MBUS_PACKING_1_5X8
:
432 return width
* 3 / 2;
433 case SOC_MBUS_PACKING_VARIABLE
:
435 case SOC_MBUS_PACKING_EXTEND32
:
440 EXPORT_SYMBOL(soc_mbus_bytes_per_line
);
442 s32
soc_mbus_image_size(const struct soc_mbus_pixelfmt
*mf
,
443 u32 bytes_per_line
, u32 height
)
445 if (mf
->layout
== SOC_MBUS_LAYOUT_PACKED
)
446 return bytes_per_line
* height
;
448 switch (mf
->packing
) {
449 case SOC_MBUS_PACKING_2X8_PADHI
:
450 case SOC_MBUS_PACKING_2X8_PADLO
:
451 return bytes_per_line
* height
* 2;
452 case SOC_MBUS_PACKING_1_5X8
:
453 return bytes_per_line
* height
* 3 / 2;
458 EXPORT_SYMBOL(soc_mbus_image_size
);
460 const struct soc_mbus_pixelfmt
*soc_mbus_find_fmtdesc(
461 enum v4l2_mbus_pixelcode code
,
462 const struct soc_mbus_lookup
*lookup
,
467 for (i
= 0; i
< n
; i
++)
468 if (lookup
[i
].code
== code
)
469 return &lookup
[i
].fmt
;
473 EXPORT_SYMBOL(soc_mbus_find_fmtdesc
);
475 const struct soc_mbus_pixelfmt
*soc_mbus_get_fmtdesc(
476 enum v4l2_mbus_pixelcode code
)
478 return soc_mbus_find_fmtdesc(code
, mbus_fmt
, ARRAY_SIZE(mbus_fmt
));
480 EXPORT_SYMBOL(soc_mbus_get_fmtdesc
);
482 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config
*cfg
,
485 unsigned long common_flags
;
486 bool hsync
= true, vsync
= true, pclk
, data
, mode
;
487 bool mipi_lanes
, mipi_clock
;
489 common_flags
= cfg
->flags
& flags
;
492 case V4L2_MBUS_PARALLEL
:
493 hsync
= common_flags
& (V4L2_MBUS_HSYNC_ACTIVE_HIGH
|
494 V4L2_MBUS_HSYNC_ACTIVE_LOW
);
495 vsync
= common_flags
& (V4L2_MBUS_VSYNC_ACTIVE_HIGH
|
496 V4L2_MBUS_VSYNC_ACTIVE_LOW
);
497 case V4L2_MBUS_BT656
:
498 pclk
= common_flags
& (V4L2_MBUS_PCLK_SAMPLE_RISING
|
499 V4L2_MBUS_PCLK_SAMPLE_FALLING
);
500 data
= common_flags
& (V4L2_MBUS_DATA_ACTIVE_HIGH
|
501 V4L2_MBUS_DATA_ACTIVE_LOW
);
502 mode
= common_flags
& (V4L2_MBUS_MASTER
| V4L2_MBUS_SLAVE
);
503 return (!hsync
|| !vsync
|| !pclk
|| !data
|| !mode
) ?
506 mipi_lanes
= common_flags
& V4L2_MBUS_CSI2_LANES
;
507 mipi_clock
= common_flags
& (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK
|
508 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK
);
509 return (!mipi_lanes
|| !mipi_clock
) ? 0 : common_flags
;
513 EXPORT_SYMBOL(soc_mbus_config_compatible
);
515 static int __init
soc_mbus_init(void)
520 static void __exit
soc_mbus_exit(void)
524 module_init(soc_mbus_init
);
525 module_exit(soc_mbus_exit
);
527 MODULE_DESCRIPTION("soc-camera media bus interface");
528 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
529 MODULE_LICENSE("GPL v2");