1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * soc-camera media bus helper routines
4  *
5  * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
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 
soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt * mf,unsigned int * numerator,unsigned int * denominator)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 
soc_mbus_bytes_per_line(u32 width,const struct soc_mbus_pixelfmt * mf)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 
soc_mbus_image_size(const struct soc_mbus_pixelfmt * mf,u32 bytes_per_line,u32 height)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 
soc_mbus_find_fmtdesc(u32 code,const struct soc_mbus_lookup * lookup,int n)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 
soc_mbus_get_fmtdesc(u32 code)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 
soc_mbus_config_compatible(const struct v4l2_mbus_config * cfg,unsigned int flags)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 		/* fall through */
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 
soc_mbus_init(void)515 static int __init soc_mbus_init(void)
516 {
517 	return 0;
518 }
519 
soc_mbus_exit(void)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");
530