Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
soc_mediabus.c
Go to the documentation of this file.
1 /*
2  * soc-camera media bus helper routines
3  *
4  * Copyright (C) 2009, Guennadi Liakhovetski <[email protected]>
5  *
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.
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 
14 #include <media/v4l2-device.h>
15 #include <media/v4l2-mediabus.h>
16 #include <media/soc_mediabus.h>
17 
18 static const struct soc_mbus_lookup mbus_fmt[] = {
19 {
21  .fmt = {
22  .fourcc = V4L2_PIX_FMT_YUYV,
23  .name = "YUYV",
24  .bits_per_sample = 8,
25  .packing = SOC_MBUS_PACKING_2X8_PADHI,
26  .order = SOC_MBUS_ORDER_LE,
27  .layout = SOC_MBUS_LAYOUT_PACKED,
28  },
29 }, {
31  .fmt = {
32  .fourcc = V4L2_PIX_FMT_YVYU,
33  .name = "YVYU",
34  .bits_per_sample = 8,
35  .packing = SOC_MBUS_PACKING_2X8_PADHI,
36  .order = SOC_MBUS_ORDER_LE,
37  .layout = SOC_MBUS_LAYOUT_PACKED,
38  },
39 }, {
41  .fmt = {
42  .fourcc = V4L2_PIX_FMT_UYVY,
43  .name = "UYVY",
44  .bits_per_sample = 8,
45  .packing = SOC_MBUS_PACKING_2X8_PADHI,
46  .order = SOC_MBUS_ORDER_LE,
47  .layout = SOC_MBUS_LAYOUT_PACKED,
48  },
49 }, {
51  .fmt = {
52  .fourcc = V4L2_PIX_FMT_VYUY,
53  .name = "VYUY",
54  .bits_per_sample = 8,
55  .packing = SOC_MBUS_PACKING_2X8_PADHI,
56  .order = SOC_MBUS_ORDER_LE,
57  .layout = SOC_MBUS_LAYOUT_PACKED,
58  },
59 }, {
61  .fmt = {
62  .fourcc = V4L2_PIX_FMT_RGB555,
63  .name = "RGB555",
64  .bits_per_sample = 8,
65  .packing = SOC_MBUS_PACKING_2X8_PADHI,
66  .order = SOC_MBUS_ORDER_LE,
67  .layout = SOC_MBUS_LAYOUT_PACKED,
68  },
69 }, {
71  .fmt = {
72  .fourcc = V4L2_PIX_FMT_RGB555X,
73  .name = "RGB555X",
74  .bits_per_sample = 8,
75  .packing = SOC_MBUS_PACKING_2X8_PADHI,
76  .order = SOC_MBUS_ORDER_LE,
77  .layout = SOC_MBUS_LAYOUT_PACKED,
78  },
79 }, {
81  .fmt = {
82  .fourcc = V4L2_PIX_FMT_RGB565,
83  .name = "RGB565",
84  .bits_per_sample = 8,
85  .packing = SOC_MBUS_PACKING_2X8_PADHI,
86  .order = SOC_MBUS_ORDER_LE,
87  .layout = SOC_MBUS_LAYOUT_PACKED,
88  },
89 }, {
91  .fmt = {
92  .fourcc = V4L2_PIX_FMT_RGB565X,
93  .name = "RGB565X",
94  .bits_per_sample = 8,
95  .packing = SOC_MBUS_PACKING_2X8_PADHI,
96  .order = SOC_MBUS_ORDER_LE,
97  .layout = SOC_MBUS_LAYOUT_PACKED,
98  },
99 }, {
100  .code = V4L2_MBUS_FMT_SBGGR8_1X8,
101  .fmt = {
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,
108  },
109 }, {
111  .fmt = {
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,
118  },
119 }, {
120  .code = V4L2_MBUS_FMT_Y8_1X8,
121  .fmt = {
122  .fourcc = V4L2_PIX_FMT_GREY,
123  .name = "Grey",
124  .bits_per_sample = 8,
125  .packing = SOC_MBUS_PACKING_NONE,
126  .order = SOC_MBUS_ORDER_LE,
127  .layout = SOC_MBUS_LAYOUT_PACKED,
128  },
129 }, {
130  .code = V4L2_MBUS_FMT_Y10_1X10,
131  .fmt = {
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,
138  },
139 }, {
141  .fmt = {
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,
148  },
149 }, {
151  .fmt = {
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,
158  },
159 }, {
161  .fmt = {
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,
168  },
169 }, {
171  .fmt = {
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,
178  },
179 }, {
180  .code = V4L2_MBUS_FMT_JPEG_1X8,
181  .fmt = {
182  .fourcc = V4L2_PIX_FMT_JPEG,
183  .name = "JPEG",
184  .bits_per_sample = 8,
185  .packing = SOC_MBUS_PACKING_VARIABLE,
186  .order = SOC_MBUS_ORDER_LE,
187  .layout = SOC_MBUS_LAYOUT_PACKED,
188  },
189 }, {
191  .fmt = {
192  .fourcc = V4L2_PIX_FMT_RGB444,
193  .name = "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,
198  },
199 }, {
201  .fmt = {
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,
208  },
209 }, {
211  .fmt = {
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,
218  },
219 }, {
220  .code = V4L2_MBUS_FMT_UYVY8_1X16,
221  .fmt = {
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,
228  },
229 }, {
230  .code = V4L2_MBUS_FMT_VYUY8_1X16,
231  .fmt = {
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,
238  },
239 }, {
240  .code = V4L2_MBUS_FMT_YUYV8_1X16,
241  .fmt = {
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,
248  },
249 }, {
250  .code = V4L2_MBUS_FMT_YVYU8_1X16,
251  .fmt = {
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,
258  },
259 }, {
260  .code = V4L2_MBUS_FMT_SGRBG8_1X8,
261  .fmt = {
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,
268  },
269 }, {
271  .fmt = {
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,
278  },
279 }, {
281  .fmt = {
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,
288  },
289 }, {
291  .fmt = {
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,
298  },
299 }, {
301  .fmt = {
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,
308  },
309 }, {
311  .fmt = {
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,
318  },
319 }, {
321  .fmt = {
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,
328  },
329 }, {
331  .fmt = {
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,
338  },
339 }, {
341  .fmt = {
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,
348  },
349 },
350 };
351 
353  unsigned int *numerator, unsigned int *denominator)
354 {
355  switch (mf->packing) {
358  *numerator = 1;
359  *denominator = 1;
360  return 0;
363  *numerator = 2;
364  *denominator = 1;
365  return 0;
367  *numerator = 3;
368  *denominator = 2;
369  return 0;
371  *numerator = 0;
372  *denominator = 1;
373  return 0;
374  }
375  return -EINVAL;
376 }
378 
380 {
381  if (mf->fourcc == V4L2_PIX_FMT_JPEG)
382  return 0;
383 
384  if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
385  return width * mf->bits_per_sample / 8;
386 
387  switch (mf->packing) {
389  return width * mf->bits_per_sample / 8;
393  return width * 2;
395  return width * 3 / 2;
397  return 0;
398  }
399  return -EINVAL;
400 }
402 
404  u32 bytes_per_line, u32 height)
405 {
406  if (mf->fourcc == V4L2_PIX_FMT_JPEG)
407  return 0;
408 
409  if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
410  return bytes_per_line * height;
411 
412  switch (mf->packing) {
415  return bytes_per_line * height * 2;
417  return bytes_per_line * height * 3 / 2;
418  default:
419  return -EINVAL;
420  }
421 }
423 
426  const struct soc_mbus_lookup *lookup,
427  int n)
428 {
429  int i;
430 
431  for (i = 0; i < n; i++)
432  if (lookup[i].code == code)
433  return &lookup[i].fmt;
434 
435  return NULL;
436 }
438 
441 {
442  return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
443 }
445 
447  unsigned int flags)
448 {
449  unsigned long common_flags;
450  bool hsync = true, vsync = true, pclk, data, mode;
451  bool mipi_lanes, mipi_clock;
452 
453  common_flags = cfg->flags & flags;
454 
455  switch (cfg->type) {
456  case V4L2_MBUS_PARALLEL:
457  hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
459  vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
461  case V4L2_MBUS_BT656:
462  pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
464  data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
466  mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
467  return (!hsync || !vsync || !pclk || !data || !mode) ?
468  0 : common_flags;
469  case V4L2_MBUS_CSI2:
470  mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
471  mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
473  return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
474  }
475  return 0;
476 }
478 
479 static int __init soc_mbus_init(void)
480 {
481  return 0;
482 }
483 
484 static void __exit soc_mbus_exit(void)
485 {
486 }
487 
488 module_init(soc_mbus_init);
489 module_exit(soc_mbus_exit);
490 
491 MODULE_DESCRIPTION("soc-camera media bus interface");
492 MODULE_AUTHOR("Guennadi Liakhovetski <[email protected]>");
493 MODULE_LICENSE("GPL v2");