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/drv-intf/soc_mediabus.h>
18 static const struct soc_mbus_lookup mbus_fmt[] = {
20 .code = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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 = MEDIA_BUS_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(
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(
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);
498 case V4L2_MBUS_BT656:
499 pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
500 V4L2_MBUS_PCLK_SAMPLE_FALLING);
501 data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
502 V4L2_MBUS_DATA_ACTIVE_LOW);
503 mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
504 return (!hsync || !vsync || !pclk || !data || !mode) ?
507 mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
508 mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
509 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
510 return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
517 EXPORT_SYMBOL(soc_mbus_config_compatible);
519 static int __init soc_mbus_init(void)
524 static void __exit soc_mbus_exit(void)
528 module_init(soc_mbus_init);
529 module_exit(soc_mbus_exit);
531 MODULE_DESCRIPTION("soc-camera media bus interface");
532 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
533 MODULE_LICENSE("GPL v2");