soc_mediabus.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <media/v4l2-device.h>
  13. #include <media/v4l2-mediabus.h>
  14. #include <media/soc_mediabus.h>
  15. static const struct soc_mbus_lookup mbus_fmt[] = {
  16. {
  17. .code = V4L2_MBUS_FMT_YUYV8_2X8,
  18. .fmt = {
  19. .fourcc = V4L2_PIX_FMT_YUYV,
  20. .name = "YUYV",
  21. .bits_per_sample = 8,
  22. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  23. .order = SOC_MBUS_ORDER_LE,
  24. },
  25. }, {
  26. .code = V4L2_MBUS_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. },
  34. }, {
  35. .code = V4L2_MBUS_FMT_UYVY8_2X8,
  36. .fmt = {
  37. .fourcc = V4L2_PIX_FMT_UYVY,
  38. .name = "UYVY",
  39. .bits_per_sample = 8,
  40. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  41. .order = SOC_MBUS_ORDER_LE,
  42. },
  43. }, {
  44. .code = V4L2_MBUS_FMT_VYUY8_2X8,
  45. .fmt = {
  46. .fourcc = V4L2_PIX_FMT_VYUY,
  47. .name = "VYUY",
  48. .bits_per_sample = 8,
  49. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  50. .order = SOC_MBUS_ORDER_LE,
  51. },
  52. }, {
  53. .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
  54. .fmt = {
  55. .fourcc = V4L2_PIX_FMT_RGB555,
  56. .name = "RGB555",
  57. .bits_per_sample = 8,
  58. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  59. .order = SOC_MBUS_ORDER_LE,
  60. },
  61. }, {
  62. .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
  63. .fmt = {
  64. .fourcc = V4L2_PIX_FMT_RGB555X,
  65. .name = "RGB555X",
  66. .bits_per_sample = 8,
  67. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  68. .order = SOC_MBUS_ORDER_LE,
  69. },
  70. }, {
  71. .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
  72. .fmt = {
  73. .fourcc = V4L2_PIX_FMT_RGB565,
  74. .name = "RGB565",
  75. .bits_per_sample = 8,
  76. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  77. .order = SOC_MBUS_ORDER_LE,
  78. },
  79. }, {
  80. .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
  81. .fmt = {
  82. .fourcc = V4L2_PIX_FMT_RGB565X,
  83. .name = "RGB565X",
  84. .bits_per_sample = 8,
  85. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  86. .order = SOC_MBUS_ORDER_LE,
  87. },
  88. }, {
  89. .code = V4L2_MBUS_FMT_SBGGR8_1X8,
  90. .fmt = {
  91. .fourcc = V4L2_PIX_FMT_SBGGR8,
  92. .name = "Bayer 8 BGGR",
  93. .bits_per_sample = 8,
  94. .packing = SOC_MBUS_PACKING_NONE,
  95. .order = SOC_MBUS_ORDER_LE,
  96. },
  97. }, {
  98. .code = V4L2_MBUS_FMT_SBGGR10_1X10,
  99. .fmt = {
  100. .fourcc = V4L2_PIX_FMT_SBGGR10,
  101. .name = "Bayer 10 BGGR",
  102. .bits_per_sample = 10,
  103. .packing = SOC_MBUS_PACKING_EXTEND16,
  104. .order = SOC_MBUS_ORDER_LE,
  105. },
  106. }, {
  107. .code = V4L2_MBUS_FMT_Y8_1X8,
  108. .fmt = {
  109. .fourcc = V4L2_PIX_FMT_GREY,
  110. .name = "Grey",
  111. .bits_per_sample = 8,
  112. .packing = SOC_MBUS_PACKING_NONE,
  113. .order = SOC_MBUS_ORDER_LE,
  114. },
  115. }, {
  116. .code = V4L2_MBUS_FMT_Y10_1X10,
  117. .fmt = {
  118. .fourcc = V4L2_PIX_FMT_Y10,
  119. .name = "Grey 10bit",
  120. .bits_per_sample = 10,
  121. .packing = SOC_MBUS_PACKING_EXTEND16,
  122. .order = SOC_MBUS_ORDER_LE,
  123. },
  124. }, {
  125. .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
  126. .fmt = {
  127. .fourcc = V4L2_PIX_FMT_SBGGR10,
  128. .name = "Bayer 10 BGGR",
  129. .bits_per_sample = 8,
  130. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  131. .order = SOC_MBUS_ORDER_LE,
  132. },
  133. }, {
  134. .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
  135. .fmt = {
  136. .fourcc = V4L2_PIX_FMT_SBGGR10,
  137. .name = "Bayer 10 BGGR",
  138. .bits_per_sample = 8,
  139. .packing = SOC_MBUS_PACKING_2X8_PADLO,
  140. .order = SOC_MBUS_ORDER_LE,
  141. },
  142. }, {
  143. .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
  144. .fmt = {
  145. .fourcc = V4L2_PIX_FMT_SBGGR10,
  146. .name = "Bayer 10 BGGR",
  147. .bits_per_sample = 8,
  148. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  149. .order = SOC_MBUS_ORDER_BE,
  150. },
  151. }, {
  152. .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
  153. .fmt = {
  154. .fourcc = V4L2_PIX_FMT_SBGGR10,
  155. .name = "Bayer 10 BGGR",
  156. .bits_per_sample = 8,
  157. .packing = SOC_MBUS_PACKING_2X8_PADLO,
  158. .order = SOC_MBUS_ORDER_BE,
  159. },
  160. }, {
  161. .code = V4L2_MBUS_FMT_JPEG_1X8,
  162. .fmt = {
  163. .fourcc = V4L2_PIX_FMT_JPEG,
  164. .name = "JPEG",
  165. .bits_per_sample = 8,
  166. .packing = SOC_MBUS_PACKING_VARIABLE,
  167. .order = SOC_MBUS_ORDER_LE,
  168. },
  169. }, {
  170. .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
  171. .fmt = {
  172. .fourcc = V4L2_PIX_FMT_RGB444,
  173. .name = "RGB444",
  174. .bits_per_sample = 8,
  175. .packing = SOC_MBUS_PACKING_2X8_PADHI,
  176. .order = SOC_MBUS_ORDER_BE,
  177. },
  178. }, {
  179. .code = V4L2_MBUS_FMT_YUYV8_1_5X8,
  180. .fmt = {
  181. .fourcc = V4L2_PIX_FMT_YUV420,
  182. .name = "YUYV 4:2:0",
  183. .bits_per_sample = 8,
  184. .packing = SOC_MBUS_PACKING_1_5X8,
  185. .order = SOC_MBUS_ORDER_LE,
  186. },
  187. }, {
  188. .code = V4L2_MBUS_FMT_YVYU8_1_5X8,
  189. .fmt = {
  190. .fourcc = V4L2_PIX_FMT_YVU420,
  191. .name = "YVYU 4:2:0",
  192. .bits_per_sample = 8,
  193. .packing = SOC_MBUS_PACKING_1_5X8,
  194. .order = SOC_MBUS_ORDER_LE,
  195. },
  196. }, {
  197. .code = V4L2_MBUS_FMT_UYVY8_1X16,
  198. .fmt = {
  199. .fourcc = V4L2_PIX_FMT_UYVY,
  200. .name = "UYVY 16bit",
  201. .bits_per_sample = 16,
  202. .packing = SOC_MBUS_PACKING_EXTEND16,
  203. .order = SOC_MBUS_ORDER_LE,
  204. },
  205. }, {
  206. .code = V4L2_MBUS_FMT_VYUY8_1X16,
  207. .fmt = {
  208. .fourcc = V4L2_PIX_FMT_VYUY,
  209. .name = "VYUY 16bit",
  210. .bits_per_sample = 16,
  211. .packing = SOC_MBUS_PACKING_EXTEND16,
  212. .order = SOC_MBUS_ORDER_LE,
  213. },
  214. }, {
  215. .code = V4L2_MBUS_FMT_YUYV8_1X16,
  216. .fmt = {
  217. .fourcc = V4L2_PIX_FMT_YUYV,
  218. .name = "YUYV 16bit",
  219. .bits_per_sample = 16,
  220. .packing = SOC_MBUS_PACKING_EXTEND16,
  221. .order = SOC_MBUS_ORDER_LE,
  222. },
  223. }, {
  224. .code = V4L2_MBUS_FMT_YVYU8_1X16,
  225. .fmt = {
  226. .fourcc = V4L2_PIX_FMT_YVYU,
  227. .name = "YVYU 16bit",
  228. .bits_per_sample = 16,
  229. .packing = SOC_MBUS_PACKING_EXTEND16,
  230. .order = SOC_MBUS_ORDER_LE,
  231. },
  232. }, {
  233. .code = V4L2_MBUS_FMT_SGRBG8_1X8,
  234. .fmt = {
  235. .fourcc = V4L2_PIX_FMT_SGRBG8,
  236. .name = "Bayer 8 GRBG",
  237. .bits_per_sample = 8,
  238. .packing = SOC_MBUS_PACKING_NONE,
  239. .order = SOC_MBUS_ORDER_LE,
  240. },
  241. }, {
  242. .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
  243. .fmt = {
  244. .fourcc = V4L2_PIX_FMT_SGRBG10DPCM8,
  245. .name = "Bayer 10 BGGR DPCM 8",
  246. .bits_per_sample = 8,
  247. .packing = SOC_MBUS_PACKING_NONE,
  248. .order = SOC_MBUS_ORDER_LE,
  249. },
  250. }, {
  251. .code = V4L2_MBUS_FMT_SGBRG10_1X10,
  252. .fmt = {
  253. .fourcc = V4L2_PIX_FMT_SGBRG10,
  254. .name = "Bayer 10 GBRG",
  255. .bits_per_sample = 10,
  256. .packing = SOC_MBUS_PACKING_EXTEND16,
  257. .order = SOC_MBUS_ORDER_LE,
  258. },
  259. }, {
  260. .code = V4L2_MBUS_FMT_SGRBG10_1X10,
  261. .fmt = {
  262. .fourcc = V4L2_PIX_FMT_SGRBG10,
  263. .name = "Bayer 10 GRBG",
  264. .bits_per_sample = 10,
  265. .packing = SOC_MBUS_PACKING_EXTEND16,
  266. .order = SOC_MBUS_ORDER_LE,
  267. },
  268. }, {
  269. .code = V4L2_MBUS_FMT_SRGGB10_1X10,
  270. .fmt = {
  271. .fourcc = V4L2_PIX_FMT_SRGGB10,
  272. .name = "Bayer 10 RGGB",
  273. .bits_per_sample = 10,
  274. .packing = SOC_MBUS_PACKING_EXTEND16,
  275. .order = SOC_MBUS_ORDER_LE,
  276. },
  277. }, {
  278. .code = V4L2_MBUS_FMT_SBGGR12_1X12,
  279. .fmt = {
  280. .fourcc = V4L2_PIX_FMT_SBGGR12,
  281. .name = "Bayer 12 BGGR",
  282. .bits_per_sample = 12,
  283. .packing = SOC_MBUS_PACKING_EXTEND16,
  284. .order = SOC_MBUS_ORDER_LE,
  285. },
  286. }, {
  287. .code = V4L2_MBUS_FMT_SGBRG12_1X12,
  288. .fmt = {
  289. .fourcc = V4L2_PIX_FMT_SGBRG12,
  290. .name = "Bayer 12 GBRG",
  291. .bits_per_sample = 12,
  292. .packing = SOC_MBUS_PACKING_EXTEND16,
  293. .order = SOC_MBUS_ORDER_LE,
  294. },
  295. }, {
  296. .code = V4L2_MBUS_FMT_SGRBG12_1X12,
  297. .fmt = {
  298. .fourcc = V4L2_PIX_FMT_SGRBG12,
  299. .name = "Bayer 12 GRBG",
  300. .bits_per_sample = 12,
  301. .packing = SOC_MBUS_PACKING_EXTEND16,
  302. .order = SOC_MBUS_ORDER_LE,
  303. },
  304. }, {
  305. .code = V4L2_MBUS_FMT_SRGGB12_1X12,
  306. .fmt = {
  307. .fourcc = V4L2_PIX_FMT_SRGGB12,
  308. .name = "Bayer 12 RGGB",
  309. .bits_per_sample = 12,
  310. .packing = SOC_MBUS_PACKING_EXTEND16,
  311. .order = SOC_MBUS_ORDER_LE,
  312. },
  313. },
  314. };
  315. int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
  316. unsigned int *numerator, unsigned int *denominator)
  317. {
  318. switch (mf->packing) {
  319. case SOC_MBUS_PACKING_NONE:
  320. case SOC_MBUS_PACKING_EXTEND16:
  321. *numerator = 1;
  322. *denominator = 1;
  323. return 0;
  324. case SOC_MBUS_PACKING_2X8_PADHI:
  325. case SOC_MBUS_PACKING_2X8_PADLO:
  326. *numerator = 2;
  327. *denominator = 1;
  328. return 0;
  329. case SOC_MBUS_PACKING_1_5X8:
  330. *numerator = 3;
  331. *denominator = 2;
  332. return 0;
  333. case SOC_MBUS_PACKING_VARIABLE:
  334. *numerator = 0;
  335. *denominator = 1;
  336. return 0;
  337. }
  338. return -EINVAL;
  339. }
  340. EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
  341. s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
  342. {
  343. switch (mf->packing) {
  344. case SOC_MBUS_PACKING_NONE:
  345. return width * mf->bits_per_sample / 8;
  346. case SOC_MBUS_PACKING_2X8_PADHI:
  347. case SOC_MBUS_PACKING_2X8_PADLO:
  348. case SOC_MBUS_PACKING_EXTEND16:
  349. return width * 2;
  350. case SOC_MBUS_PACKING_1_5X8:
  351. return width * 3 / 2;
  352. case SOC_MBUS_PACKING_VARIABLE:
  353. return 0;
  354. }
  355. return -EINVAL;
  356. }
  357. EXPORT_SYMBOL(soc_mbus_bytes_per_line);
  358. const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
  359. enum v4l2_mbus_pixelcode code,
  360. const struct soc_mbus_lookup *lookup,
  361. int n)
  362. {
  363. int i;
  364. for (i = 0; i < n; i++)
  365. if (lookup[i].code == code)
  366. return &lookup[i].fmt;
  367. return NULL;
  368. }
  369. EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
  370. const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
  371. enum v4l2_mbus_pixelcode code)
  372. {
  373. return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
  374. }
  375. EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
  376. unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
  377. unsigned int flags)
  378. {
  379. unsigned long common_flags;
  380. bool hsync = true, vsync = true, pclk, data, mode;
  381. bool mipi_lanes, mipi_clock;
  382. common_flags = cfg->flags & flags;
  383. switch (cfg->type) {
  384. case V4L2_MBUS_PARALLEL:
  385. hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
  386. V4L2_MBUS_HSYNC_ACTIVE_LOW);
  387. vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
  388. V4L2_MBUS_VSYNC_ACTIVE_LOW);
  389. case V4L2_MBUS_BT656:
  390. pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
  391. V4L2_MBUS_PCLK_SAMPLE_FALLING);
  392. data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
  393. V4L2_MBUS_DATA_ACTIVE_LOW);
  394. mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
  395. return (!hsync || !vsync || !pclk || !data || !mode) ?
  396. 0 : common_flags;
  397. case V4L2_MBUS_CSI2:
  398. mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
  399. mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
  400. V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
  401. return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
  402. }
  403. return 0;
  404. }
  405. EXPORT_SYMBOL(soc_mbus_config_compatible);
  406. static int __init soc_mbus_init(void)
  407. {
  408. return 0;
  409. }
  410. static void __exit soc_mbus_exit(void)
  411. {
  412. }
  413. module_init(soc_mbus_init);
  414. module_exit(soc_mbus_exit);
  415. MODULE_DESCRIPTION("soc-camera media bus interface");
  416. MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
  417. MODULE_LICENSE("GPL v2");