drm_fourcc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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 = DRM_FORMAT_INVALID;
  45. switch (bpp) {
  46. case 8:
  47. if (depth == 8)
  48. fmt = DRM_FORMAT_C8;
  49. break;
  50. case 16:
  51. switch (depth) {
  52. case 15:
  53. fmt = DRM_FORMAT_XRGB1555;
  54. break;
  55. case 16:
  56. fmt = DRM_FORMAT_RGB565;
  57. break;
  58. default:
  59. break;
  60. }
  61. break;
  62. case 24:
  63. if (depth == 24)
  64. fmt = DRM_FORMAT_RGB888;
  65. break;
  66. case 32:
  67. switch (depth) {
  68. case 24:
  69. fmt = DRM_FORMAT_XRGB8888;
  70. break;
  71. case 30:
  72. fmt = DRM_FORMAT_XRGB2101010;
  73. break;
  74. case 32:
  75. fmt = DRM_FORMAT_ARGB8888;
  76. break;
  77. default:
  78. break;
  79. }
  80. break;
  81. default:
  82. break;
  83. }
  84. return fmt;
  85. }
  86. EXPORT_SYMBOL(drm_mode_legacy_fb_format);
  87. /**
  88. * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
  89. * @dev: DRM device
  90. * @bpp: bits per pixels
  91. * @depth: bit depth per pixel
  92. *
  93. * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
  94. * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
  95. * and depending on the quirk_addfb_prefer_host_byte_order flag it returns
  96. * little endian byte order or host byte order framebuffer formats.
  97. */
  98. uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
  99. uint32_t bpp, uint32_t depth)
  100. {
  101. uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth);
  102. if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
  103. if (fmt == DRM_FORMAT_XRGB8888)
  104. fmt = DRM_FORMAT_HOST_XRGB8888;
  105. if (fmt == DRM_FORMAT_ARGB8888)
  106. fmt = DRM_FORMAT_HOST_ARGB8888;
  107. if (fmt == DRM_FORMAT_RGB565)
  108. fmt = DRM_FORMAT_HOST_RGB565;
  109. if (fmt == DRM_FORMAT_XRGB1555)
  110. fmt = DRM_FORMAT_HOST_XRGB1555;
  111. }
  112. if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
  113. fmt == DRM_FORMAT_XRGB2101010)
  114. fmt = DRM_FORMAT_XBGR2101010;
  115. return fmt;
  116. }
  117. EXPORT_SYMBOL(drm_driver_legacy_fb_format);
  118. /**
  119. * drm_get_format_name - fill a string with a drm fourcc format's name
  120. * @format: format to compute name of
  121. * @buf: caller-supplied buffer
  122. */
  123. const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
  124. {
  125. snprintf(buf->str, sizeof(buf->str),
  126. "%c%c%c%c %s-endian (0x%08x)",
  127. printable_char(format & 0xff),
  128. printable_char((format >> 8) & 0xff),
  129. printable_char((format >> 16) & 0xff),
  130. printable_char((format >> 24) & 0x7f),
  131. format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
  132. format);
  133. return buf->str;
  134. }
  135. EXPORT_SYMBOL(drm_get_format_name);
  136. /*
  137. * Internal function to query information for a given format. See
  138. * drm_format_info() for the public API.
  139. */
  140. const struct drm_format_info *__drm_format_info(u32 format)
  141. {
  142. static const struct drm_format_info formats[] = {
  143. { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
  144. { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
  145. { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
  146. { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  147. { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  148. { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  149. { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  150. { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  151. { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  152. { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  153. { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  154. { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  155. { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  156. { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  157. { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  158. { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  159. { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  160. { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  161. { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  162. { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  163. { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
  164. { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
  165. { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
  166. { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  167. { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  168. { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  169. { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  170. { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  171. { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  172. { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  173. { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  174. { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  175. { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
  176. { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  177. { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  178. { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  179. { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  180. { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  181. { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  182. { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  183. { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  184. { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  185. { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  186. { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  187. { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  188. { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  189. { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
  190. { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
  191. { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
  192. { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
  193. { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
  194. { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
  195. { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
  196. { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  197. { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  198. { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
  199. { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
  200. { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
  201. { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
  202. { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  203. { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  204. { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
  205. { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
  206. { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  207. { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  208. { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  209. { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
  210. { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
  211. };
  212. unsigned int i;
  213. for (i = 0; i < ARRAY_SIZE(formats); ++i) {
  214. if (formats[i].format == format)
  215. return &formats[i];
  216. }
  217. return NULL;
  218. }
  219. /**
  220. * drm_format_info - query information for a given format
  221. * @format: pixel format (DRM_FORMAT_*)
  222. *
  223. * The caller should only pass a supported pixel format to this function.
  224. * Unsupported pixel formats will generate a warning in the kernel log.
  225. *
  226. * Returns:
  227. * The instance of struct drm_format_info that describes the pixel format, or
  228. * NULL if the format is unsupported.
  229. */
  230. const struct drm_format_info *drm_format_info(u32 format)
  231. {
  232. const struct drm_format_info *info;
  233. info = __drm_format_info(format);
  234. WARN_ON(!info);
  235. return info;
  236. }
  237. EXPORT_SYMBOL(drm_format_info);
  238. /**
  239. * drm_get_format_info - query information for a given framebuffer configuration
  240. * @dev: DRM device
  241. * @mode_cmd: metadata from the userspace fb creation request
  242. *
  243. * Returns:
  244. * The instance of struct drm_format_info that describes the pixel format, or
  245. * NULL if the format is unsupported.
  246. */
  247. const struct drm_format_info *
  248. drm_get_format_info(struct drm_device *dev,
  249. const struct drm_mode_fb_cmd2 *mode_cmd)
  250. {
  251. const struct drm_format_info *info = NULL;
  252. if (dev->mode_config.funcs->get_format_info)
  253. info = dev->mode_config.funcs->get_format_info(mode_cmd);
  254. if (!info)
  255. info = drm_format_info(mode_cmd->pixel_format);
  256. return info;
  257. }
  258. EXPORT_SYMBOL(drm_get_format_info);
  259. /**
  260. * drm_format_num_planes - get the number of planes for format
  261. * @format: pixel format (DRM_FORMAT_*)
  262. *
  263. * Returns:
  264. * The number of planes used by the specified pixel format.
  265. */
  266. int drm_format_num_planes(uint32_t format)
  267. {
  268. const struct drm_format_info *info;
  269. info = drm_format_info(format);
  270. return info ? info->num_planes : 1;
  271. }
  272. EXPORT_SYMBOL(drm_format_num_planes);
  273. /**
  274. * drm_format_plane_cpp - determine the bytes per pixel value
  275. * @format: pixel format (DRM_FORMAT_*)
  276. * @plane: plane index
  277. *
  278. * Returns:
  279. * The bytes per pixel value for the specified plane.
  280. */
  281. int drm_format_plane_cpp(uint32_t format, int plane)
  282. {
  283. const struct drm_format_info *info;
  284. info = drm_format_info(format);
  285. if (!info || plane >= info->num_planes)
  286. return 0;
  287. return info->cpp[plane];
  288. }
  289. EXPORT_SYMBOL(drm_format_plane_cpp);
  290. /**
  291. * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
  292. * @format: pixel format (DRM_FORMAT_*)
  293. *
  294. * Returns:
  295. * The horizontal chroma subsampling factor for the
  296. * specified pixel format.
  297. */
  298. int drm_format_horz_chroma_subsampling(uint32_t format)
  299. {
  300. const struct drm_format_info *info;
  301. info = drm_format_info(format);
  302. return info ? info->hsub : 1;
  303. }
  304. EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
  305. /**
  306. * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
  307. * @format: pixel format (DRM_FORMAT_*)
  308. *
  309. * Returns:
  310. * The vertical chroma subsampling factor for the
  311. * specified pixel format.
  312. */
  313. int drm_format_vert_chroma_subsampling(uint32_t format)
  314. {
  315. const struct drm_format_info *info;
  316. info = drm_format_info(format);
  317. return info ? info->vsub : 1;
  318. }
  319. EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
  320. /**
  321. * drm_format_plane_width - width of the plane given the first plane
  322. * @width: width of the first plane
  323. * @format: pixel format
  324. * @plane: plane index
  325. *
  326. * Returns:
  327. * The width of @plane, given that the width of the first plane is @width.
  328. */
  329. int drm_format_plane_width(int width, uint32_t format, int plane)
  330. {
  331. const struct drm_format_info *info;
  332. info = drm_format_info(format);
  333. if (!info || plane >= info->num_planes)
  334. return 0;
  335. if (plane == 0)
  336. return width;
  337. return width / info->hsub;
  338. }
  339. EXPORT_SYMBOL(drm_format_plane_width);
  340. /**
  341. * drm_format_plane_height - height of the plane given the first plane
  342. * @height: height of the first plane
  343. * @format: pixel format
  344. * @plane: plane index
  345. *
  346. * Returns:
  347. * The height of @plane, given that the height of the first plane is @height.
  348. */
  349. int drm_format_plane_height(int height, uint32_t format, int plane)
  350. {
  351. const struct drm_format_info *info;
  352. info = drm_format_info(format);
  353. if (!info || plane >= info->num_planes)
  354. return 0;
  355. if (plane == 0)
  356. return height;
  357. return height / info->vsub;
  358. }
  359. EXPORT_SYMBOL(drm_format_plane_height);