Merge branches 'x86-cleanups-for-linus' and 'x86-cpufeature-for-linus' of git://git...
[deliverable/linux.git] / drivers / media / video / soc_mediabus.c
CommitLineData
9a74251d
GL
1/*
2 * soc-camera media bus helper routines
3 *
4 * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
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
93f116d5
GL
18static const struct soc_mbus_lookup mbus_fmt[] = {
19{
20 .code = V4L2_MBUS_FMT_YUYV8_2X8,
21 .fmt = {
9a74251d
GL
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,
ad3b81fa 27 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 28 },
93f116d5
GL
29}, {
30 .code = V4L2_MBUS_FMT_YVYU8_2X8,
31 .fmt = {
9a74251d
GL
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,
ad3b81fa 37 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 38 },
93f116d5
GL
39}, {
40 .code = V4L2_MBUS_FMT_UYVY8_2X8,
41 .fmt = {
9a74251d
GL
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,
ad3b81fa 47 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 48 },
93f116d5
GL
49}, {
50 .code = V4L2_MBUS_FMT_VYUY8_2X8,
51 .fmt = {
9a74251d
GL
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,
ad3b81fa 57 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 58 },
93f116d5
GL
59}, {
60 .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
61 .fmt = {
9a74251d
GL
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,
ad3b81fa 67 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 68 },
93f116d5
GL
69}, {
70 .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
71 .fmt = {
9a74251d
GL
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,
ad3b81fa 77 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 78 },
93f116d5
GL
79}, {
80 .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
81 .fmt = {
9a74251d
GL
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,
ad3b81fa 87 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 88 },
93f116d5
GL
89}, {
90 .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
91 .fmt = {
9a74251d
GL
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,
ad3b81fa 97 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 98 },
93f116d5
GL
99}, {
100 .code = V4L2_MBUS_FMT_SBGGR8_1X8,
101 .fmt = {
9a74251d
GL
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,
ad3b81fa 107 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 108 },
93f116d5
GL
109}, {
110 .code = V4L2_MBUS_FMT_SBGGR10_1X10,
111 .fmt = {
9a74251d
GL
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,
ad3b81fa 117 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 118 },
93f116d5
GL
119}, {
120 .code = V4L2_MBUS_FMT_Y8_1X8,
121 .fmt = {
9a74251d
GL
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,
ad3b81fa 127 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 128 },
93f116d5
GL
129}, {
130 .code = V4L2_MBUS_FMT_Y10_1X10,
131 .fmt = {
9a74251d
GL
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,
ad3b81fa 137 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 138 },
93f116d5
GL
139}, {
140 .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
141 .fmt = {
9a74251d
GL
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,
ad3b81fa 147 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 148 },
93f116d5
GL
149}, {
150 .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
151 .fmt = {
9a74251d
GL
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,
ad3b81fa 157 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 158 },
93f116d5
GL
159}, {
160 .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
161 .fmt = {
9a74251d
GL
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,
ad3b81fa 167 .layout = SOC_MBUS_LAYOUT_PACKED,
81355e40 168 },
93f116d5
GL
169}, {
170 .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
171 .fmt = {
9a74251d
GL
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,
ad3b81fa 177 .layout = SOC_MBUS_LAYOUT_PACKED,
9a74251d 178 },
93f116d5
GL
179}, {
180 .code = V4L2_MBUS_FMT_JPEG_1X8,
181 .fmt = {
64149deb
KL
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,
ad3b81fa 187 .layout = SOC_MBUS_LAYOUT_PACKED,
64149deb 188 },
e23b961d
GL
189}, {
190 .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
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,
ad3b81fa 197 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
198 },
199}, {
200 .code = V4L2_MBUS_FMT_YUYV8_1_5X8,
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,
ad3b81fa 207 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
208 },
209}, {
210 .code = V4L2_MBUS_FMT_YVYU8_1_5X8,
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,
ad3b81fa 217 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
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,
ad3b81fa 227 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
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,
ad3b81fa 237 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
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,
ad3b81fa 247 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
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,
ad3b81fa 257 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
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,
ad3b81fa 267 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
268 },
269}, {
270 .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
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,
ad3b81fa 277 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
278 },
279}, {
280 .code = V4L2_MBUS_FMT_SGBRG10_1X10,
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,
ad3b81fa 287 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
288 },
289}, {
290 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
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,
ad3b81fa 297 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
298 },
299}, {
300 .code = V4L2_MBUS_FMT_SRGGB10_1X10,
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,
ad3b81fa 307 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
308 },
309}, {
310 .code = V4L2_MBUS_FMT_SBGGR12_1X12,
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,
ad3b81fa 317 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
318 },
319}, {
320 .code = V4L2_MBUS_FMT_SGBRG12_1X12,
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,
ad3b81fa 327 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
328 },
329}, {
330 .code = V4L2_MBUS_FMT_SGRBG12_1X12,
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,
ad3b81fa 337 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d
GL
338 },
339}, {
340 .code = V4L2_MBUS_FMT_SRGGB12_1X12,
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,
ad3b81fa 347 .layout = SOC_MBUS_LAYOUT_PACKED,
e23b961d 348 },
93f116d5 349},
9a74251d
GL
350};
351
cc552b62
GL
352int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
353 unsigned int *numerator, unsigned int *denominator)
48a3c773
AP
354{
355 switch (mf->packing) {
356 case SOC_MBUS_PACKING_NONE:
357 case SOC_MBUS_PACKING_EXTEND16:
cc552b62
GL
358 *numerator = 1;
359 *denominator = 1;
360 return 0;
48a3c773
AP
361 case SOC_MBUS_PACKING_2X8_PADHI:
362 case SOC_MBUS_PACKING_2X8_PADLO:
cc552b62
GL
363 *numerator = 2;
364 *denominator = 1;
365 return 0;
366 case SOC_MBUS_PACKING_1_5X8:
367 *numerator = 3;
368 *denominator = 2;
369 return 0;
64149deb 370 case SOC_MBUS_PACKING_VARIABLE:
cc552b62
GL
371 *numerator = 0;
372 *denominator = 1;
64149deb 373 return 0;
48a3c773
AP
374 }
375 return -EINVAL;
376}
377EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
378
9a74251d
GL
379s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
380{
4e0e620c
LP
381 if (mf->layout != SOC_MBUS_LAYOUT_PACKED)
382 return width * mf->bits_per_sample / 8;
383
9a74251d
GL
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:
390 return width * 2;
cc552b62
GL
391 case SOC_MBUS_PACKING_1_5X8:
392 return width * 3 / 2;
64149deb
KL
393 case SOC_MBUS_PACKING_VARIABLE:
394 return 0;
9a74251d
GL
395 }
396 return -EINVAL;
397}
398EXPORT_SYMBOL(soc_mbus_bytes_per_line);
399
8929c963
LP
400s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
401 u32 bytes_per_line, u32 height)
402{
403 if (mf->layout == SOC_MBUS_LAYOUT_PACKED)
404 return bytes_per_line * height;
405
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;
412 default:
413 return -EINVAL;
414 }
415}
416EXPORT_SYMBOL(soc_mbus_image_size);
417
93f116d5
GL
418const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
419 enum v4l2_mbus_pixelcode code,
420 const struct soc_mbus_lookup *lookup,
421 int n)
422{
423 int i;
424
425 for (i = 0; i < n; i++)
426 if (lookup[i].code == code)
427 return &lookup[i].fmt;
428
429 return NULL;
430}
431EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
432
9a74251d
GL
433const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
434 enum v4l2_mbus_pixelcode code)
435{
93f116d5 436 return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
9a74251d
GL
437}
438EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
439
32c69fcc
GL
440unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
441 unsigned int flags)
442{
443 unsigned long common_flags;
444 bool hsync = true, vsync = true, pclk, data, mode;
445 bool mipi_lanes, mipi_clock;
446
447 common_flags = cfg->flags & flags;
448
449 switch (cfg->type) {
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) ?
462 0 : common_flags;
463 case V4L2_MBUS_CSI2:
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;
468 }
469 return 0;
470}
471EXPORT_SYMBOL(soc_mbus_config_compatible);
472
9a74251d
GL
473static int __init soc_mbus_init(void)
474{
475 return 0;
476}
477
478static void __exit soc_mbus_exit(void)
479{
480}
481
482module_init(soc_mbus_init);
483module_exit(soc_mbus_exit);
484
485MODULE_DESCRIPTION("soc-camera media bus interface");
486MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
487MODULE_LICENSE("GPL v2");
This page took 0.235604 seconds and 5 git commands to generate.