This source file includes following definitions.
- soc_mbus_samples_per_pixel
- soc_mbus_bytes_per_line
- soc_mbus_image_size
- soc_mbus_find_fmtdesc
- soc_mbus_get_fmtdesc
- soc_mbus_config_compatible
- soc_mbus_init
- soc_mbus_exit
1
2
3
4
5
6
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9
10 #include <media/v4l2-device.h>
11 #include <media/v4l2-mediabus.h>
12 #include <media/drv-intf/soc_mediabus.h>
13
14 static const struct soc_mbus_lookup mbus_fmt[] = {
15 {
16 .code = MEDIA_BUS_FMT_YUYV8_2X8,
17 .fmt = {
18 .fourcc = V4L2_PIX_FMT_YUYV,
19 .name = "YUYV",
20 .bits_per_sample = 8,
21 .packing = SOC_MBUS_PACKING_2X8_PADHI,
22 .order = SOC_MBUS_ORDER_LE,
23 .layout = SOC_MBUS_LAYOUT_PACKED,
24 },
25 }, {
26 .code = MEDIA_BUS_FMT_YVYU8_2X8,
27 .fmt = {
28 .fourcc = V4L2_PIX_FMT_YVYU,
29 .name = "YVYU",
30 .bits_per_sample = 8,
31 .packing = SOC_MBUS_PACKING_2X8_PADHI,
32 .order = SOC_MBUS_ORDER_LE,
33 .layout = SOC_MBUS_LAYOUT_PACKED,
34 },
35 }, {
36 .code = MEDIA_BUS_FMT_UYVY8_2X8,
37 .fmt = {
38 .fourcc = V4L2_PIX_FMT_UYVY,
39 .name = "UYVY",
40 .bits_per_sample = 8,
41 .packing = SOC_MBUS_PACKING_2X8_PADHI,
42 .order = SOC_MBUS_ORDER_LE,
43 .layout = SOC_MBUS_LAYOUT_PACKED,
44 },
45 }, {
46 .code = MEDIA_BUS_FMT_VYUY8_2X8,
47 .fmt = {
48 .fourcc = V4L2_PIX_FMT_VYUY,
49 .name = "VYUY",
50 .bits_per_sample = 8,
51 .packing = SOC_MBUS_PACKING_2X8_PADHI,
52 .order = SOC_MBUS_ORDER_LE,
53 .layout = SOC_MBUS_LAYOUT_PACKED,
54 },
55 }, {
56 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
57 .fmt = {
58 .fourcc = V4L2_PIX_FMT_RGB555,
59 .name = "RGB555",
60 .bits_per_sample = 8,
61 .packing = SOC_MBUS_PACKING_2X8_PADHI,
62 .order = SOC_MBUS_ORDER_LE,
63 .layout = SOC_MBUS_LAYOUT_PACKED,
64 },
65 }, {
66 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
67 .fmt = {
68 .fourcc = V4L2_PIX_FMT_RGB555X,
69 .name = "RGB555X",
70 .bits_per_sample = 8,
71 .packing = SOC_MBUS_PACKING_2X8_PADHI,
72 .order = SOC_MBUS_ORDER_BE,
73 .layout = SOC_MBUS_LAYOUT_PACKED,
74 },
75 }, {
76 .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
77 .fmt = {
78 .fourcc = V4L2_PIX_FMT_RGB565,
79 .name = "RGB565",
80 .bits_per_sample = 8,
81 .packing = SOC_MBUS_PACKING_2X8_PADHI,
82 .order = SOC_MBUS_ORDER_LE,
83 .layout = SOC_MBUS_LAYOUT_PACKED,
84 },
85 }, {
86 .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
87 .fmt = {
88 .fourcc = V4L2_PIX_FMT_RGB565X,
89 .name = "RGB565X",
90 .bits_per_sample = 8,
91 .packing = SOC_MBUS_PACKING_2X8_PADHI,
92 .order = SOC_MBUS_ORDER_BE,
93 .layout = SOC_MBUS_LAYOUT_PACKED,
94 },
95 }, {
96 .code = MEDIA_BUS_FMT_RGB666_1X18,
97 .fmt = {
98 .fourcc = V4L2_PIX_FMT_RGB32,
99 .name = "RGB666/32bpp",
100 .bits_per_sample = 18,
101 .packing = SOC_MBUS_PACKING_EXTEND32,
102 .order = SOC_MBUS_ORDER_LE,
103 },
104 }, {
105 .code = MEDIA_BUS_FMT_RGB888_1X24,
106 .fmt = {
107 .fourcc = V4L2_PIX_FMT_RGB32,
108 .name = "RGB888/32bpp",
109 .bits_per_sample = 24,
110 .packing = SOC_MBUS_PACKING_EXTEND32,
111 .order = SOC_MBUS_ORDER_LE,
112 },
113 }, {
114 .code = MEDIA_BUS_FMT_RGB888_2X12_BE,
115 .fmt = {
116 .fourcc = V4L2_PIX_FMT_RGB32,
117 .name = "RGB888/32bpp",
118 .bits_per_sample = 12,
119 .packing = SOC_MBUS_PACKING_EXTEND32,
120 .order = SOC_MBUS_ORDER_BE,
121 },
122 }, {
123 .code = MEDIA_BUS_FMT_RGB888_2X12_LE,
124 .fmt = {
125 .fourcc = V4L2_PIX_FMT_RGB32,
126 .name = "RGB888/32bpp",
127 .bits_per_sample = 12,
128 .packing = SOC_MBUS_PACKING_EXTEND32,
129 .order = SOC_MBUS_ORDER_LE,
130 },
131 }, {
132 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
133 .fmt = {
134 .fourcc = V4L2_PIX_FMT_SBGGR8,
135 .name = "Bayer 8 BGGR",
136 .bits_per_sample = 8,
137 .packing = SOC_MBUS_PACKING_NONE,
138 .order = SOC_MBUS_ORDER_LE,
139 .layout = SOC_MBUS_LAYOUT_PACKED,
140 },
141 }, {
142 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
143 .fmt = {
144 .fourcc = V4L2_PIX_FMT_SBGGR10,
145 .name = "Bayer 10 BGGR",
146 .bits_per_sample = 10,
147 .packing = SOC_MBUS_PACKING_EXTEND16,
148 .order = SOC_MBUS_ORDER_LE,
149 .layout = SOC_MBUS_LAYOUT_PACKED,
150 },
151 }, {
152 .code = MEDIA_BUS_FMT_Y8_1X8,
153 .fmt = {
154 .fourcc = V4L2_PIX_FMT_GREY,
155 .name = "Grey",
156 .bits_per_sample = 8,
157 .packing = SOC_MBUS_PACKING_NONE,
158 .order = SOC_MBUS_ORDER_LE,
159 .layout = SOC_MBUS_LAYOUT_PACKED,
160 },
161 }, {
162 .code = MEDIA_BUS_FMT_Y10_1X10,
163 .fmt = {
164 .fourcc = V4L2_PIX_FMT_Y10,
165 .name = "Grey 10bit",
166 .bits_per_sample = 10,
167 .packing = SOC_MBUS_PACKING_EXTEND16,
168 .order = SOC_MBUS_ORDER_LE,
169 .layout = SOC_MBUS_LAYOUT_PACKED,
170 },
171 }, {
172 .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
173 .fmt = {
174 .fourcc = V4L2_PIX_FMT_SBGGR10,
175 .name = "Bayer 10 BGGR",
176 .bits_per_sample = 8,
177 .packing = SOC_MBUS_PACKING_2X8_PADHI,
178 .order = SOC_MBUS_ORDER_LE,
179 .layout = SOC_MBUS_LAYOUT_PACKED,
180 },
181 }, {
182 .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE,
183 .fmt = {
184 .fourcc = V4L2_PIX_FMT_SBGGR10,
185 .name = "Bayer 10 BGGR",
186 .bits_per_sample = 8,
187 .packing = SOC_MBUS_PACKING_2X8_PADLO,
188 .order = SOC_MBUS_ORDER_LE,
189 .layout = SOC_MBUS_LAYOUT_PACKED,
190 },
191 }, {
192 .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE,
193 .fmt = {
194 .fourcc = V4L2_PIX_FMT_SBGGR10,
195 .name = "Bayer 10 BGGR",
196 .bits_per_sample = 8,
197 .packing = SOC_MBUS_PACKING_2X8_PADHI,
198 .order = SOC_MBUS_ORDER_BE,
199 .layout = SOC_MBUS_LAYOUT_PACKED,
200 },
201 }, {
202 .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE,
203 .fmt = {
204 .fourcc = V4L2_PIX_FMT_SBGGR10,
205 .name = "Bayer 10 BGGR",
206 .bits_per_sample = 8,
207 .packing = SOC_MBUS_PACKING_2X8_PADLO,
208 .order = SOC_MBUS_ORDER_BE,
209 .layout = SOC_MBUS_LAYOUT_PACKED,
210 },
211 }, {
212 .code = MEDIA_BUS_FMT_JPEG_1X8,
213 .fmt = {
214 .fourcc = V4L2_PIX_FMT_JPEG,
215 .name = "JPEG",
216 .bits_per_sample = 8,
217 .packing = SOC_MBUS_PACKING_VARIABLE,
218 .order = SOC_MBUS_ORDER_LE,
219 .layout = SOC_MBUS_LAYOUT_PACKED,
220 },
221 }, {
222 .code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE,
223 .fmt = {
224 .fourcc = V4L2_PIX_FMT_RGB444,
225 .name = "RGB444",
226 .bits_per_sample = 8,
227 .packing = SOC_MBUS_PACKING_2X8_PADHI,
228 .order = SOC_MBUS_ORDER_BE,
229 .layout = SOC_MBUS_LAYOUT_PACKED,
230 },
231 }, {
232 .code = MEDIA_BUS_FMT_YUYV8_1_5X8,
233 .fmt = {
234 .fourcc = V4L2_PIX_FMT_YUV420,
235 .name = "YUYV 4:2:0",
236 .bits_per_sample = 8,
237 .packing = SOC_MBUS_PACKING_1_5X8,
238 .order = SOC_MBUS_ORDER_LE,
239 .layout = SOC_MBUS_LAYOUT_PACKED,
240 },
241 }, {
242 .code = MEDIA_BUS_FMT_YVYU8_1_5X8,
243 .fmt = {
244 .fourcc = V4L2_PIX_FMT_YVU420,
245 .name = "YVYU 4:2:0",
246 .bits_per_sample = 8,
247 .packing = SOC_MBUS_PACKING_1_5X8,
248 .order = SOC_MBUS_ORDER_LE,
249 .layout = SOC_MBUS_LAYOUT_PACKED,
250 },
251 }, {
252 .code = MEDIA_BUS_FMT_UYVY8_1X16,
253 .fmt = {
254 .fourcc = V4L2_PIX_FMT_UYVY,
255 .name = "UYVY 16bit",
256 .bits_per_sample = 16,
257 .packing = SOC_MBUS_PACKING_EXTEND16,
258 .order = SOC_MBUS_ORDER_LE,
259 .layout = SOC_MBUS_LAYOUT_PACKED,
260 },
261 }, {
262 .code = MEDIA_BUS_FMT_VYUY8_1X16,
263 .fmt = {
264 .fourcc = V4L2_PIX_FMT_VYUY,
265 .name = "VYUY 16bit",
266 .bits_per_sample = 16,
267 .packing = SOC_MBUS_PACKING_EXTEND16,
268 .order = SOC_MBUS_ORDER_LE,
269 .layout = SOC_MBUS_LAYOUT_PACKED,
270 },
271 }, {
272 .code = MEDIA_BUS_FMT_YUYV8_1X16,
273 .fmt = {
274 .fourcc = V4L2_PIX_FMT_YUYV,
275 .name = "YUYV 16bit",
276 .bits_per_sample = 16,
277 .packing = SOC_MBUS_PACKING_EXTEND16,
278 .order = SOC_MBUS_ORDER_LE,
279 .layout = SOC_MBUS_LAYOUT_PACKED,
280 },
281 }, {
282 .code = MEDIA_BUS_FMT_YVYU8_1X16,
283 .fmt = {
284 .fourcc = V4L2_PIX_FMT_YVYU,
285 .name = "YVYU 16bit",
286 .bits_per_sample = 16,
287 .packing = SOC_MBUS_PACKING_EXTEND16,
288 .order = SOC_MBUS_ORDER_LE,
289 .layout = SOC_MBUS_LAYOUT_PACKED,
290 },
291 }, {
292 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
293 .fmt = {
294 .fourcc = V4L2_PIX_FMT_SGRBG8,
295 .name = "Bayer 8 GRBG",
296 .bits_per_sample = 8,
297 .packing = SOC_MBUS_PACKING_NONE,
298 .order = SOC_MBUS_ORDER_LE,
299 .layout = SOC_MBUS_LAYOUT_PACKED,
300 },
301 }, {
302 .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
303 .fmt = {
304 .fourcc = V4L2_PIX_FMT_SGRBG10DPCM8,
305 .name = "Bayer 10 BGGR DPCM 8",
306 .bits_per_sample = 8,
307 .packing = SOC_MBUS_PACKING_NONE,
308 .order = SOC_MBUS_ORDER_LE,
309 .layout = SOC_MBUS_LAYOUT_PACKED,
310 },
311 }, {
312 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
313 .fmt = {
314 .fourcc = V4L2_PIX_FMT_SGBRG10,
315 .name = "Bayer 10 GBRG",
316 .bits_per_sample = 10,
317 .packing = SOC_MBUS_PACKING_EXTEND16,
318 .order = SOC_MBUS_ORDER_LE,
319 .layout = SOC_MBUS_LAYOUT_PACKED,
320 },
321 }, {
322 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
323 .fmt = {
324 .fourcc = V4L2_PIX_FMT_SGRBG10,
325 .name = "Bayer 10 GRBG",
326 .bits_per_sample = 10,
327 .packing = SOC_MBUS_PACKING_EXTEND16,
328 .order = SOC_MBUS_ORDER_LE,
329 .layout = SOC_MBUS_LAYOUT_PACKED,
330 },
331 }, {
332 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
333 .fmt = {
334 .fourcc = V4L2_PIX_FMT_SRGGB10,
335 .name = "Bayer 10 RGGB",
336 .bits_per_sample = 10,
337 .packing = SOC_MBUS_PACKING_EXTEND16,
338 .order = SOC_MBUS_ORDER_LE,
339 .layout = SOC_MBUS_LAYOUT_PACKED,
340 },
341 }, {
342 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
343 .fmt = {
344 .fourcc = V4L2_PIX_FMT_SBGGR12,
345 .name = "Bayer 12 BGGR",
346 .bits_per_sample = 12,
347 .packing = SOC_MBUS_PACKING_EXTEND16,
348 .order = SOC_MBUS_ORDER_LE,
349 .layout = SOC_MBUS_LAYOUT_PACKED,
350 },
351 }, {
352 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
353 .fmt = {
354 .fourcc = V4L2_PIX_FMT_SGBRG12,
355 .name = "Bayer 12 GBRG",
356 .bits_per_sample = 12,
357 .packing = SOC_MBUS_PACKING_EXTEND16,
358 .order = SOC_MBUS_ORDER_LE,
359 .layout = SOC_MBUS_LAYOUT_PACKED,
360 },
361 }, {
362 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
363 .fmt = {
364 .fourcc = V4L2_PIX_FMT_SGRBG12,
365 .name = "Bayer 12 GRBG",
366 .bits_per_sample = 12,
367 .packing = SOC_MBUS_PACKING_EXTEND16,
368 .order = SOC_MBUS_ORDER_LE,
369 .layout = SOC_MBUS_LAYOUT_PACKED,
370 },
371 }, {
372 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
373 .fmt = {
374 .fourcc = V4L2_PIX_FMT_SRGGB12,
375 .name = "Bayer 12 RGGB",
376 .bits_per_sample = 12,
377 .packing = SOC_MBUS_PACKING_EXTEND16,
378 .order = SOC_MBUS_ORDER_LE,
379 .layout = SOC_MBUS_LAYOUT_PACKED,
380 },
381 },
382 };
383
384 int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
385 unsigned int *numerator, unsigned int *denominator)
386 {
387 switch (mf->packing) {
388 case SOC_MBUS_PACKING_NONE:
389 case SOC_MBUS_PACKING_EXTEND16:
390 *numerator = 1;
391 *denominator = 1;
392 return 0;
393 case SOC_MBUS_PACKING_EXTEND32:
394 *numerator = 1;
395 *denominator = 1;
396 return 0;
397 case SOC_MBUS_PACKING_2X8_PADHI:
398 case SOC_MBUS_PACKING_2X8_PADLO:
399 *numerator = 2;
400 *denominator = 1;
401 return 0;
402 case SOC_MBUS_PACKING_1_5X8:
403 *numerator = 3;
404 *denominator = 2;
405 return 0;
406 case SOC_MBUS_PACKING_VARIABLE:
407 *numerator = 0;
408 *denominator = 1;
409 return 0;
410 }
411 return -EINVAL;
412 }
413 EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
414
415 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
416 {
417 if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
418 return width * mf->bits_per_sample / 8;
419
420 switch (mf->packing) {
421 case SOC_MBUS_PACKING_NONE:
422 return width * mf->bits_per_sample / 8;
423 case SOC_MBUS_PACKING_2X8_PADHI:
424 case SOC_MBUS_PACKING_2X8_PADLO:
425 case SOC_MBUS_PACKING_EXTEND16:
426 return width * 2;
427 case SOC_MBUS_PACKING_1_5X8:
428 return width * 3 / 2;
429 case SOC_MBUS_PACKING_VARIABLE:
430 return 0;
431 case SOC_MBUS_PACKING_EXTEND32:
432 return width * 4;
433 }
434 return -EINVAL;
435 }
436 EXPORT_SYMBOL(soc_mbus_bytes_per_line);
437
438 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
439 u32 bytes_per_line, u32 height)
440 {
441 if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
442 return bytes_per_line * height;
443
444 switch (mf->packing) {
445 case SOC_MBUS_PACKING_2X8_PADHI:
446 case SOC_MBUS_PACKING_2X8_PADLO:
447 return bytes_per_line * height * 2;
448 case SOC_MBUS_PACKING_1_5X8:
449 return bytes_per_line * height * 3 / 2;
450 default:
451 return -EINVAL;
452 }
453 }
454 EXPORT_SYMBOL(soc_mbus_image_size);
455
456 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
457 u32 code,
458 const struct soc_mbus_lookup *lookup,
459 int n)
460 {
461 int i;
462
463 for (i = 0; i < n; i++)
464 if (lookup[i].code == code)
465 return &lookup[i].fmt;
466
467 return NULL;
468 }
469 EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
470
471 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
472 u32 code)
473 {
474 return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
475 }
476 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
477
478 unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
479 unsigned int flags)
480 {
481 unsigned long common_flags;
482 bool hsync = true, vsync = true, pclk, data, mode;
483 bool mipi_lanes, mipi_clock;
484
485 common_flags = cfg->flags & flags;
486
487 switch (cfg->type) {
488 case V4L2_MBUS_PARALLEL:
489 hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
490 V4L2_MBUS_HSYNC_ACTIVE_LOW);
491 vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
492 V4L2_MBUS_VSYNC_ACTIVE_LOW);
493
494 case V4L2_MBUS_BT656:
495 pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
496 V4L2_MBUS_PCLK_SAMPLE_FALLING);
497 data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
498 V4L2_MBUS_DATA_ACTIVE_LOW);
499 mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
500 return (!hsync || !vsync || !pclk || !data || !mode) ?
501 0 : common_flags;
502 case V4L2_MBUS_CSI2_DPHY:
503 mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
504 mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
505 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
506 return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
507 default:
508 WARN_ON(1);
509 return -EINVAL;
510 }
511 return 0;
512 }
513 EXPORT_SYMBOL(soc_mbus_config_compatible);
514
515 static int __init soc_mbus_init(void)
516 {
517 return 0;
518 }
519
520 static void __exit soc_mbus_exit(void)
521 {
522 }
523
524 module_init(soc_mbus_init);
525 module_exit(soc_mbus_exit);
526
527 MODULE_DESCRIPTION("soc-camera media bus interface");
528 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
529 MODULE_LICENSE("GPL v2");