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_LE
,
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_LE
,
97 .layout
= SOC_MBUS_LAYOUT_PACKED
,
100 .code
= V4L2_MBUS_FMT_SBGGR8_1X8
,
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
,
110 .code
= V4L2_MBUS_FMT_SBGGR10_1X10
,
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
,
120 .code
= V4L2_MBUS_FMT_Y8_1X8
,
122 .fourcc
= V4L2_PIX_FMT_GREY
,
124 .bits_per_sample
= 8,
125 .packing
= SOC_MBUS_PACKING_NONE
,
126 .order
= SOC_MBUS_ORDER_LE
,
127 .layout
= SOC_MBUS_LAYOUT_PACKED
,
130 .code
= V4L2_MBUS_FMT_Y10_1X10
,
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
,
140 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE
,
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
,
150 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE
,
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
,
160 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE
,
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
,
170 .code
= V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE
,
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
,
180 .code
= V4L2_MBUS_FMT_JPEG_1X8
,
182 .fourcc
= V4L2_PIX_FMT_JPEG
,
184 .bits_per_sample
= 8,
185 .packing
= SOC_MBUS_PACKING_VARIABLE
,
186 .order
= SOC_MBUS_ORDER_LE
,
187 .layout
= SOC_MBUS_LAYOUT_PACKED
,
190 .code
= V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE
,
192 .fourcc
= V4L2_PIX_FMT_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
,
200 .code
= V4L2_MBUS_FMT_YUYV8_1_5X8
,
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
,
210 .code
= V4L2_MBUS_FMT_YVYU8_1_5X8
,
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
,
220 .code
= V4L2_MBUS_FMT_UYVY8_1X16
,
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
,
230 .code
= V4L2_MBUS_FMT_VYUY8_1X16
,
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
,
240 .code
= V4L2_MBUS_FMT_YUYV8_1X16
,
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
,
250 .code
= V4L2_MBUS_FMT_YVYU8_1X16
,
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
,
260 .code
= V4L2_MBUS_FMT_SGRBG8_1X8
,
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
,
270 .code
= V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8
,
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
,
280 .code
= V4L2_MBUS_FMT_SGBRG10_1X10
,
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
,
290 .code
= V4L2_MBUS_FMT_SGRBG10_1X10
,
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
,
300 .code
= V4L2_MBUS_FMT_SRGGB10_1X10
,
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
,
310 .code
= V4L2_MBUS_FMT_SBGGR12_1X12
,
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
,
320 .code
= V4L2_MBUS_FMT_SGBRG12_1X12
,
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
,
330 .code
= V4L2_MBUS_FMT_SGRBG12_1X12
,
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
,
340 .code
= V4L2_MBUS_FMT_SRGGB12_1X12
,
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
,
352 int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt
*mf
,
353 unsigned int *numerator
, unsigned int *denominator
)
355 switch (mf
->packing
) {
356 case SOC_MBUS_PACKING_NONE
:
357 case SOC_MBUS_PACKING_EXTEND16
:
361 case SOC_MBUS_PACKING_2X8_PADHI
:
362 case SOC_MBUS_PACKING_2X8_PADLO
:
366 case SOC_MBUS_PACKING_1_5X8
:
370 case SOC_MBUS_PACKING_VARIABLE
:
377 EXPORT_SYMBOL(soc_mbus_samples_per_pixel
);
379 s32
soc_mbus_bytes_per_line(u32 width
, const struct soc_mbus_pixelfmt
*mf
)
381 if (mf
->layout
!= SOC_MBUS_LAYOUT_PACKED
)
382 return width
* mf
->bits_per_sample
/ 8;
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
:
391 case SOC_MBUS_PACKING_1_5X8
:
392 return width
* 3 / 2;
393 case SOC_MBUS_PACKING_VARIABLE
:
398 EXPORT_SYMBOL(soc_mbus_bytes_per_line
);
400 s32
soc_mbus_image_size(const struct soc_mbus_pixelfmt
*mf
,
401 u32 bytes_per_line
, u32 height
)
403 if (mf
->layout
== SOC_MBUS_LAYOUT_PACKED
)
404 return bytes_per_line
* height
;
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;
416 EXPORT_SYMBOL(soc_mbus_image_size
);
418 const struct soc_mbus_pixelfmt
*soc_mbus_find_fmtdesc(
419 enum v4l2_mbus_pixelcode code
,
420 const struct soc_mbus_lookup
*lookup
,
425 for (i
= 0; i
< n
; i
++)
426 if (lookup
[i
].code
== code
)
427 return &lookup
[i
].fmt
;
431 EXPORT_SYMBOL(soc_mbus_find_fmtdesc
);
433 const struct soc_mbus_pixelfmt
*soc_mbus_get_fmtdesc(
434 enum v4l2_mbus_pixelcode code
)
436 return soc_mbus_find_fmtdesc(code
, mbus_fmt
, ARRAY_SIZE(mbus_fmt
));
438 EXPORT_SYMBOL(soc_mbus_get_fmtdesc
);
440 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config
*cfg
,
443 unsigned long common_flags
;
444 bool hsync
= true, vsync
= true, pclk
, data
, mode
;
445 bool mipi_lanes
, mipi_clock
;
447 common_flags
= cfg
->flags
& flags
;
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
) ?
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
;
471 EXPORT_SYMBOL(soc_mbus_config_compatible
);
473 static int __init
soc_mbus_init(void)
478 static void __exit
soc_mbus_exit(void)
482 module_init(soc_mbus_init
);
483 module_exit(soc_mbus_exit
);
485 MODULE_DESCRIPTION("soc-camera media bus interface");
486 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
487 MODULE_LICENSE("GPL v2");