drm_fourcc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  3. *
  4. * DRM core format related functions
  5. *
  6. * Permission to use, copy, modify, distribute, and sell this software and its
  7. * documentation for any purpose is hereby granted without fee, provided that
  8. * the above copyright notice appear in all copies and that both that copyright
  9. * notice and this permission notice appear in supporting documentation, and
  10. * that the name of the copyright holders not be used in advertising or
  11. * publicity pertaining to distribution of the software without specific,
  12. * written prior permission. The copyright holders make no representations
  13. * about the suitability of this software for any purpose. It is provided "as
  14. * is" without express or implied warranty.
  15. *
  16. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  18. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  20. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  21. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22. * OF THIS SOFTWARE.
  23. */
  24. #include <linux/bug.h>
  25. #include <linux/ctype.h>
  26. #include <linux/export.h>
  27. #include <linux/kernel.h>
  28. #include <drm/drmP.h>
  29. #include <drm/drm_fourcc.h>
  30. static char printable_char(int c)
  31. {
  32. return isascii(c) && isprint(c) ? c : '?';
  33. }
  34. /**
  35. * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
  36. * @bpp: bits per pixels
  37. * @depth: bit depth per pixel
  38. *
  39. * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
  40. * Useful in fbdev emulation code, since that deals in those values.
  41. */
  42. uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
  43. {
  44. uint32_t fmt;
  45. switch (bpp) {
  46. case 8:
  47. fmt = DRM_FORMAT_C8;
  48. break;
  49. case 16:
  50. if (depth == 15)
  51. fmt = DRM_FORMAT_XRGB1555;
  52. else
  53. fmt = DRM_FORMAT_RGB565;
  54. break;
  55. case 24:
  56. fmt = DRM_FORMAT_RGB888;
  57. break;
  58. case 32:
  59. if (depth == 24)
  60. fmt = DRM_FORMAT_XRGB8888;
  61. else if (depth == 30)
  62. fmt = DRM_FORMAT_XRGB2101010;
  63. else
  64. fmt = DRM_FORMAT_ARGB8888;
  65. break;
  66. default:
  67. DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
  68. fmt = DRM_FORMAT_XRGB8888;
  69. break;
  70. }
  71. return fmt;
  72. }
  73. EXPORT_SYMBOL(drm_mode_legacy_fb_format);
  74. /**
  75. * drm_get_format_name - return a string for drm fourcc format
  76. * @format: format to compute name of
  77. *
  78. * Note that the buffer returned by this function is owned by the caller
  79. * and will need to be freed using kfree().
  80. */
  81. char *drm_get_format_name(uint32_t format)
  82. {
  83. char *buf = kmalloc(32, GFP_KERNEL);
  84. snprintf(buf, 32,
  85. "%c%c%c%c %s-endian (0x%08x)",
  86. printable_char(format & 0xff),
  87. printable_char((format >> 8) & 0xff),
  88. printable_char((format >> 16) & 0xff),
  89. printable_char((format >> 24) & 0x7f),
  90. format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
  91. format);
  92. return buf;
  93. }
  94. EXPORT_SYMBOL(drm_get_format_name);
  95. /**
  96. * drm_fb_get_bpp_depth - get the bpp/depth values for format
  97. * @format: pixel format (DRM_FORMAT_*)
  98. * @depth: storage for the depth value
  99. * @bpp: storage for the bpp value
  100. *
  101. * This only supports RGB formats here for compat with code that doesn't use
  102. * pixel formats directly yet.
  103. */
  104. void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
  105. int *bpp)
  106. {
  107. char *format_name;
  108. switch (format) {
  109. case DRM_FORMAT_C8:
  110. case DRM_FORMAT_RGB332:
  111. case DRM_FORMAT_BGR233:
  112. *depth = 8;
  113. *bpp = 8;
  114. break;
  115. case DRM_FORMAT_XRGB1555:
  116. case DRM_FORMAT_XBGR1555:
  117. case DRM_FORMAT_RGBX5551:
  118. case DRM_FORMAT_BGRX5551:
  119. case DRM_FORMAT_ARGB1555:
  120. case DRM_FORMAT_ABGR1555:
  121. case DRM_FORMAT_RGBA5551:
  122. case DRM_FORMAT_BGRA5551:
  123. *depth = 15;
  124. *bpp = 16;
  125. break;
  126. case DRM_FORMAT_RGB565:
  127. case DRM_FORMAT_BGR565:
  128. *depth = 16;
  129. *bpp = 16;
  130. break;
  131. case DRM_FORMAT_RGB888:
  132. case DRM_FORMAT_BGR888:
  133. *depth = 24;
  134. *bpp = 24;
  135. break;
  136. case DRM_FORMAT_XRGB8888:
  137. case DRM_FORMAT_XBGR8888:
  138. case DRM_FORMAT_RGBX8888:
  139. case DRM_FORMAT_BGRX8888:
  140. *depth = 24;
  141. *bpp = 32;
  142. break;
  143. case DRM_FORMAT_XRGB2101010:
  144. case DRM_FORMAT_XBGR2101010:
  145. case DRM_FORMAT_RGBX1010102:
  146. case DRM_FORMAT_BGRX1010102:
  147. case DRM_FORMAT_ARGB2101010:
  148. case DRM_FORMAT_ABGR2101010:
  149. case DRM_FORMAT_RGBA1010102:
  150. case DRM_FORMAT_BGRA1010102:
  151. *depth = 30;
  152. *bpp = 32;
  153. break;
  154. case DRM_FORMAT_ARGB8888:
  155. case DRM_FORMAT_ABGR8888:
  156. case DRM_FORMAT_RGBA8888:
  157. case DRM_FORMAT_BGRA8888:
  158. *depth = 32;
  159. *bpp = 32;
  160. break;
  161. default:
  162. format_name = drm_get_format_name(format);
  163. DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
  164. kfree(format_name);
  165. *depth = 0;
  166. *bpp = 0;
  167. break;
  168. }
  169. }
  170. EXPORT_SYMBOL(drm_fb_get_bpp_depth);
  171. /**
  172. * drm_format_num_planes - get the number of planes for format
  173. * @format: pixel format (DRM_FORMAT_*)
  174. *
  175. * Returns:
  176. * The number of planes used by the specified pixel format.
  177. */
  178. int drm_format_num_planes(uint32_t format)
  179. {
  180. switch (format) {
  181. case DRM_FORMAT_YUV410:
  182. case DRM_FORMAT_YVU410:
  183. case DRM_FORMAT_YUV411:
  184. case DRM_FORMAT_YVU411:
  185. case DRM_FORMAT_YUV420:
  186. case DRM_FORMAT_YVU420:
  187. case DRM_FORMAT_YUV422:
  188. case DRM_FORMAT_YVU422:
  189. case DRM_FORMAT_YUV444:
  190. case DRM_FORMAT_YVU444:
  191. return 3;
  192. case DRM_FORMAT_NV12:
  193. case DRM_FORMAT_NV21:
  194. case DRM_FORMAT_NV16:
  195. case DRM_FORMAT_NV61:
  196. case DRM_FORMAT_NV24:
  197. case DRM_FORMAT_NV42:
  198. return 2;
  199. default:
  200. return 1;
  201. }
  202. }
  203. EXPORT_SYMBOL(drm_format_num_planes);
  204. /**
  205. * drm_format_plane_cpp - determine the bytes per pixel value
  206. * @format: pixel format (DRM_FORMAT_*)
  207. * @plane: plane index
  208. *
  209. * Returns:
  210. * The bytes per pixel value for the specified plane.
  211. */
  212. int drm_format_plane_cpp(uint32_t format, int plane)
  213. {
  214. unsigned int depth;
  215. int bpp;
  216. if (plane >= drm_format_num_planes(format))
  217. return 0;
  218. switch (format) {
  219. case DRM_FORMAT_YUYV:
  220. case DRM_FORMAT_YVYU:
  221. case DRM_FORMAT_UYVY:
  222. case DRM_FORMAT_VYUY:
  223. return 2;
  224. case DRM_FORMAT_NV12:
  225. case DRM_FORMAT_NV21:
  226. case DRM_FORMAT_NV16:
  227. case DRM_FORMAT_NV61:
  228. case DRM_FORMAT_NV24:
  229. case DRM_FORMAT_NV42:
  230. return plane ? 2 : 1;
  231. case DRM_FORMAT_YUV410:
  232. case DRM_FORMAT_YVU410:
  233. case DRM_FORMAT_YUV411:
  234. case DRM_FORMAT_YVU411:
  235. case DRM_FORMAT_YUV420:
  236. case DRM_FORMAT_YVU420:
  237. case DRM_FORMAT_YUV422:
  238. case DRM_FORMAT_YVU422:
  239. case DRM_FORMAT_YUV444:
  240. case DRM_FORMAT_YVU444:
  241. return 1;
  242. default:
  243. drm_fb_get_bpp_depth(format, &depth, &bpp);
  244. return bpp >> 3;
  245. }
  246. }
  247. EXPORT_SYMBOL(drm_format_plane_cpp);
  248. /**
  249. * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
  250. * @format: pixel format (DRM_FORMAT_*)
  251. *
  252. * Returns:
  253. * The horizontal chroma subsampling factor for the
  254. * specified pixel format.
  255. */
  256. int drm_format_horz_chroma_subsampling(uint32_t format)
  257. {
  258. switch (format) {
  259. case DRM_FORMAT_YUV411:
  260. case DRM_FORMAT_YVU411:
  261. case DRM_FORMAT_YUV410:
  262. case DRM_FORMAT_YVU410:
  263. return 4;
  264. case DRM_FORMAT_YUYV:
  265. case DRM_FORMAT_YVYU:
  266. case DRM_FORMAT_UYVY:
  267. case DRM_FORMAT_VYUY:
  268. case DRM_FORMAT_NV12:
  269. case DRM_FORMAT_NV21:
  270. case DRM_FORMAT_NV16:
  271. case DRM_FORMAT_NV61:
  272. case DRM_FORMAT_YUV422:
  273. case DRM_FORMAT_YVU422:
  274. case DRM_FORMAT_YUV420:
  275. case DRM_FORMAT_YVU420:
  276. return 2;
  277. default:
  278. return 1;
  279. }
  280. }
  281. EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
  282. /**
  283. * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
  284. * @format: pixel format (DRM_FORMAT_*)
  285. *
  286. * Returns:
  287. * The vertical chroma subsampling factor for the
  288. * specified pixel format.
  289. */
  290. int drm_format_vert_chroma_subsampling(uint32_t format)
  291. {
  292. switch (format) {
  293. case DRM_FORMAT_YUV410:
  294. case DRM_FORMAT_YVU410:
  295. return 4;
  296. case DRM_FORMAT_YUV420:
  297. case DRM_FORMAT_YVU420:
  298. case DRM_FORMAT_NV12:
  299. case DRM_FORMAT_NV21:
  300. return 2;
  301. default:
  302. return 1;
  303. }
  304. }
  305. EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
  306. /**
  307. * drm_format_plane_width - width of the plane given the first plane
  308. * @width: width of the first plane
  309. * @format: pixel format
  310. * @plane: plane index
  311. *
  312. * Returns:
  313. * The width of @plane, given that the width of the first plane is @width.
  314. */
  315. int drm_format_plane_width(int width, uint32_t format, int plane)
  316. {
  317. if (plane >= drm_format_num_planes(format))
  318. return 0;
  319. if (plane == 0)
  320. return width;
  321. return width / drm_format_horz_chroma_subsampling(format);
  322. }
  323. EXPORT_SYMBOL(drm_format_plane_width);
  324. /**
  325. * drm_format_plane_height - height of the plane given the first plane
  326. * @height: height of the first plane
  327. * @format: pixel format
  328. * @plane: plane index
  329. *
  330. * Returns:
  331. * The height of @plane, given that the height of the first plane is @height.
  332. */
  333. int drm_format_plane_height(int height, uint32_t format, int plane)
  334. {
  335. if (plane >= drm_format_num_planes(format))
  336. return 0;
  337. if (plane == 0)
  338. return height;
  339. return height / drm_format_vert_chroma_subsampling(format);
  340. }
  341. EXPORT_SYMBOL(drm_format_plane_height);