drm_fourcc.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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_get_format_name - return a string for drm fourcc format
  36. * @format: format to compute name of
  37. *
  38. * Note that the buffer used by this function is globally shared and owned by
  39. * the function itself.
  40. *
  41. * FIXME: This isn't really multithreading safe.
  42. */
  43. const char *drm_get_format_name(uint32_t format)
  44. {
  45. static char buf[32];
  46. snprintf(buf, sizeof(buf),
  47. "%c%c%c%c %s-endian (0x%08x)",
  48. printable_char(format & 0xff),
  49. printable_char((format >> 8) & 0xff),
  50. printable_char((format >> 16) & 0xff),
  51. printable_char((format >> 24) & 0x7f),
  52. format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
  53. format);
  54. return buf;
  55. }
  56. EXPORT_SYMBOL(drm_get_format_name);
  57. /**
  58. * drm_fb_get_bpp_depth - get the bpp/depth values for format
  59. * @format: pixel format (DRM_FORMAT_*)
  60. * @depth: storage for the depth value
  61. * @bpp: storage for the bpp value
  62. *
  63. * This only supports RGB formats here for compat with code that doesn't use
  64. * pixel formats directly yet.
  65. */
  66. void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
  67. int *bpp)
  68. {
  69. switch (format) {
  70. case DRM_FORMAT_C8:
  71. case DRM_FORMAT_RGB332:
  72. case DRM_FORMAT_BGR233:
  73. *depth = 8;
  74. *bpp = 8;
  75. break;
  76. case DRM_FORMAT_XRGB1555:
  77. case DRM_FORMAT_XBGR1555:
  78. case DRM_FORMAT_RGBX5551:
  79. case DRM_FORMAT_BGRX5551:
  80. case DRM_FORMAT_ARGB1555:
  81. case DRM_FORMAT_ABGR1555:
  82. case DRM_FORMAT_RGBA5551:
  83. case DRM_FORMAT_BGRA5551:
  84. *depth = 15;
  85. *bpp = 16;
  86. break;
  87. case DRM_FORMAT_RGB565:
  88. case DRM_FORMAT_BGR565:
  89. *depth = 16;
  90. *bpp = 16;
  91. break;
  92. case DRM_FORMAT_RGB888:
  93. case DRM_FORMAT_BGR888:
  94. *depth = 24;
  95. *bpp = 24;
  96. break;
  97. case DRM_FORMAT_XRGB8888:
  98. case DRM_FORMAT_XBGR8888:
  99. case DRM_FORMAT_RGBX8888:
  100. case DRM_FORMAT_BGRX8888:
  101. *depth = 24;
  102. *bpp = 32;
  103. break;
  104. case DRM_FORMAT_XRGB2101010:
  105. case DRM_FORMAT_XBGR2101010:
  106. case DRM_FORMAT_RGBX1010102:
  107. case DRM_FORMAT_BGRX1010102:
  108. case DRM_FORMAT_ARGB2101010:
  109. case DRM_FORMAT_ABGR2101010:
  110. case DRM_FORMAT_RGBA1010102:
  111. case DRM_FORMAT_BGRA1010102:
  112. *depth = 30;
  113. *bpp = 32;
  114. break;
  115. case DRM_FORMAT_ARGB8888:
  116. case DRM_FORMAT_ABGR8888:
  117. case DRM_FORMAT_RGBA8888:
  118. case DRM_FORMAT_BGRA8888:
  119. *depth = 32;
  120. *bpp = 32;
  121. break;
  122. default:
  123. DRM_DEBUG_KMS("unsupported pixel format %s\n",
  124. drm_get_format_name(format));
  125. *depth = 0;
  126. *bpp = 0;
  127. break;
  128. }
  129. }
  130. EXPORT_SYMBOL(drm_fb_get_bpp_depth);
  131. /**
  132. * drm_format_num_planes - get the number of planes for format
  133. * @format: pixel format (DRM_FORMAT_*)
  134. *
  135. * Returns:
  136. * The number of planes used by the specified pixel format.
  137. */
  138. int drm_format_num_planes(uint32_t format)
  139. {
  140. switch (format) {
  141. case DRM_FORMAT_YUV410:
  142. case DRM_FORMAT_YVU410:
  143. case DRM_FORMAT_YUV411:
  144. case DRM_FORMAT_YVU411:
  145. case DRM_FORMAT_YUV420:
  146. case DRM_FORMAT_YVU420:
  147. case DRM_FORMAT_YUV422:
  148. case DRM_FORMAT_YVU422:
  149. case DRM_FORMAT_YUV444:
  150. case DRM_FORMAT_YVU444:
  151. return 3;
  152. case DRM_FORMAT_NV12:
  153. case DRM_FORMAT_NV21:
  154. case DRM_FORMAT_NV16:
  155. case DRM_FORMAT_NV61:
  156. case DRM_FORMAT_NV24:
  157. case DRM_FORMAT_NV42:
  158. return 2;
  159. default:
  160. return 1;
  161. }
  162. }
  163. EXPORT_SYMBOL(drm_format_num_planes);
  164. /**
  165. * drm_format_plane_cpp - determine the bytes per pixel value
  166. * @format: pixel format (DRM_FORMAT_*)
  167. * @plane: plane index
  168. *
  169. * Returns:
  170. * The bytes per pixel value for the specified plane.
  171. */
  172. int drm_format_plane_cpp(uint32_t format, int plane)
  173. {
  174. unsigned int depth;
  175. int bpp;
  176. if (plane >= drm_format_num_planes(format))
  177. return 0;
  178. switch (format) {
  179. case DRM_FORMAT_YUYV:
  180. case DRM_FORMAT_YVYU:
  181. case DRM_FORMAT_UYVY:
  182. case DRM_FORMAT_VYUY:
  183. return 2;
  184. case DRM_FORMAT_NV12:
  185. case DRM_FORMAT_NV21:
  186. case DRM_FORMAT_NV16:
  187. case DRM_FORMAT_NV61:
  188. case DRM_FORMAT_NV24:
  189. case DRM_FORMAT_NV42:
  190. return plane ? 2 : 1;
  191. case DRM_FORMAT_YUV410:
  192. case DRM_FORMAT_YVU410:
  193. case DRM_FORMAT_YUV411:
  194. case DRM_FORMAT_YVU411:
  195. case DRM_FORMAT_YUV420:
  196. case DRM_FORMAT_YVU420:
  197. case DRM_FORMAT_YUV422:
  198. case DRM_FORMAT_YVU422:
  199. case DRM_FORMAT_YUV444:
  200. case DRM_FORMAT_YVU444:
  201. return 1;
  202. default:
  203. drm_fb_get_bpp_depth(format, &depth, &bpp);
  204. return bpp >> 3;
  205. }
  206. }
  207. EXPORT_SYMBOL(drm_format_plane_cpp);
  208. /**
  209. * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
  210. * @format: pixel format (DRM_FORMAT_*)
  211. *
  212. * Returns:
  213. * The horizontal chroma subsampling factor for the
  214. * specified pixel format.
  215. */
  216. int drm_format_horz_chroma_subsampling(uint32_t format)
  217. {
  218. switch (format) {
  219. case DRM_FORMAT_YUV411:
  220. case DRM_FORMAT_YVU411:
  221. case DRM_FORMAT_YUV410:
  222. case DRM_FORMAT_YVU410:
  223. return 4;
  224. case DRM_FORMAT_YUYV:
  225. case DRM_FORMAT_YVYU:
  226. case DRM_FORMAT_UYVY:
  227. case DRM_FORMAT_VYUY:
  228. case DRM_FORMAT_NV12:
  229. case DRM_FORMAT_NV21:
  230. case DRM_FORMAT_NV16:
  231. case DRM_FORMAT_NV61:
  232. case DRM_FORMAT_YUV422:
  233. case DRM_FORMAT_YVU422:
  234. case DRM_FORMAT_YUV420:
  235. case DRM_FORMAT_YVU420:
  236. return 2;
  237. default:
  238. return 1;
  239. }
  240. }
  241. EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
  242. /**
  243. * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
  244. * @format: pixel format (DRM_FORMAT_*)
  245. *
  246. * Returns:
  247. * The vertical chroma subsampling factor for the
  248. * specified pixel format.
  249. */
  250. int drm_format_vert_chroma_subsampling(uint32_t format)
  251. {
  252. switch (format) {
  253. case DRM_FORMAT_YUV410:
  254. case DRM_FORMAT_YVU410:
  255. return 4;
  256. case DRM_FORMAT_YUV420:
  257. case DRM_FORMAT_YVU420:
  258. case DRM_FORMAT_NV12:
  259. case DRM_FORMAT_NV21:
  260. return 2;
  261. default:
  262. return 1;
  263. }
  264. }
  265. EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
  266. /**
  267. * drm_format_plane_width - width of the plane given the first plane
  268. * @width: width of the first plane
  269. * @format: pixel format
  270. * @plane: plane index
  271. *
  272. * Returns:
  273. * The width of @plane, given that the width of the first plane is @width.
  274. */
  275. int drm_format_plane_width(int width, uint32_t format, int plane)
  276. {
  277. if (plane >= drm_format_num_planes(format))
  278. return 0;
  279. if (plane == 0)
  280. return width;
  281. return width / drm_format_horz_chroma_subsampling(format);
  282. }
  283. EXPORT_SYMBOL(drm_format_plane_width);
  284. /**
  285. * drm_format_plane_height - height of the plane given the first plane
  286. * @height: height of the first plane
  287. * @format: pixel format
  288. * @plane: plane index
  289. *
  290. * Returns:
  291. * The height of @plane, given that the height of the first plane is @height.
  292. */
  293. int drm_format_plane_height(int height, uint32_t format, int plane)
  294. {
  295. if (plane >= drm_format_num_planes(format))
  296. return 0;
  297. if (plane == 0)
  298. return height;
  299. return height / drm_format_vert_chroma_subsampling(format);
  300. }
  301. EXPORT_SYMBOL(drm_format_plane_height);