soc_mediabus.c 12 KB

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