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->fourcc == V4L2_PIX_FMT_JPEG)
384 if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
385 return width * mf->bits_per_sample / 8;
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:
394 case SOC_MBUS_PACKING_1_5X8:
395 return width * 3 / 2;
396 case SOC_MBUS_PACKING_VARIABLE:
401 EXPORT_SYMBOL(soc_mbus_bytes_per_line);
403 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
404 u32 bytes_per_line, u32 height)
406 if (mf->fourcc == V4L2_PIX_FMT_JPEG)
409 if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
410 return bytes_per_line * height;
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;
422 EXPORT_SYMBOL(soc_mbus_image_size);
424 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
425 enum v4l2_mbus_pixelcode code,
426 const struct soc_mbus_lookup *lookup,
431 for (i = 0; i < n; i++)
432 if (lookup[i].code == code)
433 return &lookup[i].fmt;
437 EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
439 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
440 enum v4l2_mbus_pixelcode code)
442 return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
444 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
446 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
449 unsigned long common_flags;
450 bool hsync = true, vsync = true, pclk, data, mode;
451 bool mipi_lanes, mipi_clock;
453 common_flags = cfg->flags & flags;
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) ?
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;
477 EXPORT_SYMBOL(soc_mbus_config_compatible);
479 static int __init soc_mbus_init(void)
484 static void __exit soc_mbus_exit(void)
488 module_init(soc_mbus_init);
489 module_exit(soc_mbus_exit);
491 MODULE_DESCRIPTION("soc-camera media bus interface");
492 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
493 MODULE_LICENSE("GPL v2");