Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
0003  *
0004  * DRM core format related functions
0005  *
0006  * Permission to use, copy, modify, distribute, and sell this software and its
0007  * documentation for any purpose is hereby granted without fee, provided that
0008  * the above copyright notice appear in all copies and that both that copyright
0009  * notice and this permission notice appear in supporting documentation, and
0010  * that the name of the copyright holders not be used in advertising or
0011  * publicity pertaining to distribution of the software without specific,
0012  * written prior permission.  The copyright holders make no representations
0013  * about the suitability of this software for any purpose.  It is provided "as
0014  * is" without express or implied warranty.
0015  *
0016  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0017  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0018  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0019  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0020  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0021  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0022  * OF THIS SOFTWARE.
0023  */
0024 
0025 #include <linux/bug.h>
0026 #include <linux/ctype.h>
0027 #include <linux/export.h>
0028 #include <linux/kernel.h>
0029 
0030 #include <drm/drm_device.h>
0031 #include <drm/drm_fourcc.h>
0032 
0033 /**
0034  * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
0035  * @bpp: bits per pixels
0036  * @depth: bit depth per pixel
0037  *
0038  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
0039  * Useful in fbdev emulation code, since that deals in those values.
0040  */
0041 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
0042 {
0043     uint32_t fmt = DRM_FORMAT_INVALID;
0044 
0045     switch (bpp) {
0046     case 8:
0047         if (depth == 8)
0048             fmt = DRM_FORMAT_C8;
0049         break;
0050 
0051     case 16:
0052         switch (depth) {
0053         case 15:
0054             fmt = DRM_FORMAT_XRGB1555;
0055             break;
0056         case 16:
0057             fmt = DRM_FORMAT_RGB565;
0058             break;
0059         default:
0060             break;
0061         }
0062         break;
0063 
0064     case 24:
0065         if (depth == 24)
0066             fmt = DRM_FORMAT_RGB888;
0067         break;
0068 
0069     case 32:
0070         switch (depth) {
0071         case 24:
0072             fmt = DRM_FORMAT_XRGB8888;
0073             break;
0074         case 30:
0075             fmt = DRM_FORMAT_XRGB2101010;
0076             break;
0077         case 32:
0078             fmt = DRM_FORMAT_ARGB8888;
0079             break;
0080         default:
0081             break;
0082         }
0083         break;
0084 
0085     default:
0086         break;
0087     }
0088 
0089     return fmt;
0090 }
0091 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
0092 
0093 /**
0094  * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
0095  * @dev: DRM device
0096  * @bpp: bits per pixels
0097  * @depth: bit depth per pixel
0098  *
0099  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
0100  * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
0101  * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag
0102  * it returns little endian byte order or host byte order framebuffer formats.
0103  */
0104 uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
0105                      uint32_t bpp, uint32_t depth)
0106 {
0107     uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth);
0108 
0109     if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
0110         if (fmt == DRM_FORMAT_XRGB8888)
0111             fmt = DRM_FORMAT_HOST_XRGB8888;
0112         if (fmt == DRM_FORMAT_ARGB8888)
0113             fmt = DRM_FORMAT_HOST_ARGB8888;
0114         if (fmt == DRM_FORMAT_RGB565)
0115             fmt = DRM_FORMAT_HOST_RGB565;
0116         if (fmt == DRM_FORMAT_XRGB1555)
0117             fmt = DRM_FORMAT_HOST_XRGB1555;
0118     }
0119 
0120     if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
0121         fmt == DRM_FORMAT_XRGB2101010)
0122         fmt = DRM_FORMAT_XBGR2101010;
0123 
0124     return fmt;
0125 }
0126 EXPORT_SYMBOL(drm_driver_legacy_fb_format);
0127 
0128 /*
0129  * Internal function to query information for a given format. See
0130  * drm_format_info() for the public API.
0131  */
0132 const struct drm_format_info *__drm_format_info(u32 format)
0133 {
0134     static const struct drm_format_info formats[] = {
0135         { .format = DRM_FORMAT_C8,      .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
0136         { .format = DRM_FORMAT_R8,      .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
0137         { .format = DRM_FORMAT_R10,     .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0138         { .format = DRM_FORMAT_R12,     .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0139         { .format = DRM_FORMAT_RGB332,      .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
0140         { .format = DRM_FORMAT_BGR233,      .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
0141         { .format = DRM_FORMAT_XRGB4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0142         { .format = DRM_FORMAT_XBGR4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0143         { .format = DRM_FORMAT_RGBX4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0144         { .format = DRM_FORMAT_BGRX4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0145         { .format = DRM_FORMAT_ARGB4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0146         { .format = DRM_FORMAT_ABGR4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0147         { .format = DRM_FORMAT_RGBA4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0148         { .format = DRM_FORMAT_BGRA4444,    .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0149         { .format = DRM_FORMAT_XRGB1555,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0150         { .format = DRM_FORMAT_XBGR1555,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0151         { .format = DRM_FORMAT_RGBX5551,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0152         { .format = DRM_FORMAT_BGRX5551,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0153         { .format = DRM_FORMAT_ARGB1555,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0154         { .format = DRM_FORMAT_ABGR1555,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0155         { .format = DRM_FORMAT_RGBA5551,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0156         { .format = DRM_FORMAT_BGRA5551,    .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0157         { .format = DRM_FORMAT_RGB565,      .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0158         { .format = DRM_FORMAT_BGR565,      .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
0159         { .format = DRM_FORMAT_RGB888,      .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
0160         { .format = DRM_FORMAT_BGR888,      .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
0161         { .format = DRM_FORMAT_XRGB8888,    .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0162         { .format = DRM_FORMAT_XBGR8888,    .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0163         { .format = DRM_FORMAT_RGBX8888,    .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0164         { .format = DRM_FORMAT_BGRX8888,    .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0165         { .format = DRM_FORMAT_RGB565_A8,   .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0166         { .format = DRM_FORMAT_BGR565_A8,   .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0167         { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0168         { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0169         { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0170         { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
0171         { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0172         { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0173         { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0174         { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0175         { .format = DRM_FORMAT_ARGB8888,    .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0176         { .format = DRM_FORMAT_ABGR8888,    .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0177         { .format = DRM_FORMAT_RGBA8888,    .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0178         { .format = DRM_FORMAT_BGRA8888,    .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0179         { .format = DRM_FORMAT_XRGB16161616F,   .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
0180         { .format = DRM_FORMAT_XBGR16161616F,   .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
0181         { .format = DRM_FORMAT_ARGB16161616F,   .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0182         { .format = DRM_FORMAT_ABGR16161616F,   .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0183         { .format = DRM_FORMAT_AXBXGXRX106106106106, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0184         { .format = DRM_FORMAT_XRGB16161616,    .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
0185         { .format = DRM_FORMAT_XBGR16161616,    .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
0186         { .format = DRM_FORMAT_ARGB16161616,    .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0187         { .format = DRM_FORMAT_ABGR16161616,    .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0188         { .format = DRM_FORMAT_RGB888_A8,   .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0189         { .format = DRM_FORMAT_BGR888_A8,   .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0190         { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0191         { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0192         { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0193         { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
0194         { .format = DRM_FORMAT_YUV410,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
0195         { .format = DRM_FORMAT_YVU410,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
0196         { .format = DRM_FORMAT_YUV411,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
0197         { .format = DRM_FORMAT_YVU411,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
0198         { .format = DRM_FORMAT_YUV420,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
0199         { .format = DRM_FORMAT_YVU420,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
0200         { .format = DRM_FORMAT_YUV422,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0201         { .format = DRM_FORMAT_YVU422,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0202         { .format = DRM_FORMAT_YUV444,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0203         { .format = DRM_FORMAT_YVU444,      .depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0204         { .format = DRM_FORMAT_NV12,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
0205         { .format = DRM_FORMAT_NV21,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
0206         { .format = DRM_FORMAT_NV16,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0207         { .format = DRM_FORMAT_NV61,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0208         { .format = DRM_FORMAT_NV24,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0209         { .format = DRM_FORMAT_NV42,        .depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0210         { .format = DRM_FORMAT_YUYV,        .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0211         { .format = DRM_FORMAT_YVYU,        .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0212         { .format = DRM_FORMAT_UYVY,        .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0213         { .format = DRM_FORMAT_VYUY,        .depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0214         { .format = DRM_FORMAT_XYUV8888,    .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0215         { .format = DRM_FORMAT_VUY888,          .depth = 0,  .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0216         { .format = DRM_FORMAT_AYUV,        .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
0217         { .format = DRM_FORMAT_Y210,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0218         { .format = DRM_FORMAT_Y212,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0219         { .format = DRM_FORMAT_Y216,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
0220         { .format = DRM_FORMAT_Y410,            .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
0221         { .format = DRM_FORMAT_Y412,            .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
0222         { .format = DRM_FORMAT_Y416,            .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
0223         { .format = DRM_FORMAT_XVYU2101010, .depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0224         { .format = DRM_FORMAT_XVYU12_16161616, .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0225         { .format = DRM_FORMAT_XVYU16161616,    .depth = 0,  .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
0226         { .format = DRM_FORMAT_Y0L0,        .depth = 0,  .num_planes = 1,
0227           .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
0228           .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true },
0229         { .format = DRM_FORMAT_X0L0,        .depth = 0,  .num_planes = 1,
0230           .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
0231           .hsub = 2, .vsub = 2, .is_yuv = true },
0232         { .format = DRM_FORMAT_Y0L2,        .depth = 0,  .num_planes = 1,
0233           .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
0234           .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true },
0235         { .format = DRM_FORMAT_X0L2,        .depth = 0,  .num_planes = 1,
0236           .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
0237           .hsub = 2, .vsub = 2, .is_yuv = true },
0238         { .format = DRM_FORMAT_P010,            .depth = 0,  .num_planes = 2,
0239           .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
0240           .hsub = 2, .vsub = 2, .is_yuv = true},
0241         { .format = DRM_FORMAT_P012,        .depth = 0,  .num_planes = 2,
0242           .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
0243            .hsub = 2, .vsub = 2, .is_yuv = true},
0244         { .format = DRM_FORMAT_P016,        .depth = 0,  .num_planes = 2,
0245           .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
0246           .hsub = 2, .vsub = 2, .is_yuv = true},
0247         { .format = DRM_FORMAT_P210,        .depth = 0,
0248           .num_planes = 2, .char_per_block = { 2, 4, 0 },
0249           .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
0250           .vsub = 1, .is_yuv = true },
0251         { .format = DRM_FORMAT_VUY101010,   .depth = 0,
0252           .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1,
0253           .is_yuv = true },
0254         { .format = DRM_FORMAT_YUV420_8BIT,     .depth = 0,
0255           .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2,
0256           .is_yuv = true },
0257         { .format = DRM_FORMAT_YUV420_10BIT,    .depth = 0,
0258           .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2,
0259           .is_yuv = true },
0260         { .format = DRM_FORMAT_NV15,        .depth = 0,
0261           .num_planes = 2, .char_per_block = { 5, 5, 0 },
0262           .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
0263           .vsub = 2, .is_yuv = true },
0264         { .format = DRM_FORMAT_Q410,        .depth = 0,
0265           .num_planes = 3, .char_per_block = { 2, 2, 2 },
0266           .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0,
0267           .vsub = 0, .is_yuv = true },
0268         { .format = DRM_FORMAT_Q401,        .depth = 0,
0269           .num_planes = 3, .char_per_block = { 2, 2, 2 },
0270           .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0,
0271           .vsub = 0, .is_yuv = true },
0272         { .format = DRM_FORMAT_P030,            .depth = 0,  .num_planes = 2,
0273           .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 },
0274           .hsub = 2, .vsub = 2, .is_yuv = true},
0275     };
0276 
0277     unsigned int i;
0278 
0279     for (i = 0; i < ARRAY_SIZE(formats); ++i) {
0280         if (formats[i].format == format)
0281             return &formats[i];
0282     }
0283 
0284     return NULL;
0285 }
0286 
0287 /**
0288  * drm_format_info - query information for a given format
0289  * @format: pixel format (DRM_FORMAT_*)
0290  *
0291  * The caller should only pass a supported pixel format to this function.
0292  * Unsupported pixel formats will generate a warning in the kernel log.
0293  *
0294  * Returns:
0295  * The instance of struct drm_format_info that describes the pixel format, or
0296  * NULL if the format is unsupported.
0297  */
0298 const struct drm_format_info *drm_format_info(u32 format)
0299 {
0300     const struct drm_format_info *info;
0301 
0302     info = __drm_format_info(format);
0303     WARN_ON(!info);
0304     return info;
0305 }
0306 EXPORT_SYMBOL(drm_format_info);
0307 
0308 /**
0309  * drm_get_format_info - query information for a given framebuffer configuration
0310  * @dev: DRM device
0311  * @mode_cmd: metadata from the userspace fb creation request
0312  *
0313  * Returns:
0314  * The instance of struct drm_format_info that describes the pixel format, or
0315  * NULL if the format is unsupported.
0316  */
0317 const struct drm_format_info *
0318 drm_get_format_info(struct drm_device *dev,
0319             const struct drm_mode_fb_cmd2 *mode_cmd)
0320 {
0321     const struct drm_format_info *info = NULL;
0322 
0323     if (dev->mode_config.funcs->get_format_info)
0324         info = dev->mode_config.funcs->get_format_info(mode_cmd);
0325 
0326     if (!info)
0327         info = drm_format_info(mode_cmd->pixel_format);
0328 
0329     return info;
0330 }
0331 EXPORT_SYMBOL(drm_get_format_info);
0332 
0333 /**
0334  * drm_format_info_block_width - width in pixels of block.
0335  * @info: pixel format info
0336  * @plane: plane index
0337  *
0338  * Returns:
0339  * The width in pixels of a block, depending on the plane index.
0340  */
0341 unsigned int drm_format_info_block_width(const struct drm_format_info *info,
0342                      int plane)
0343 {
0344     if (!info || plane < 0 || plane >= info->num_planes)
0345         return 0;
0346 
0347     if (!info->block_w[plane])
0348         return 1;
0349     return info->block_w[plane];
0350 }
0351 EXPORT_SYMBOL(drm_format_info_block_width);
0352 
0353 /**
0354  * drm_format_info_block_height - height in pixels of a block
0355  * @info: pixel format info
0356  * @plane: plane index
0357  *
0358  * Returns:
0359  * The height in pixels of a block, depending on the plane index.
0360  */
0361 unsigned int drm_format_info_block_height(const struct drm_format_info *info,
0362                       int plane)
0363 {
0364     if (!info || plane < 0 || plane >= info->num_planes)
0365         return 0;
0366 
0367     if (!info->block_h[plane])
0368         return 1;
0369     return info->block_h[plane];
0370 }
0371 EXPORT_SYMBOL(drm_format_info_block_height);
0372 
0373 /**
0374  * drm_format_info_min_pitch - computes the minimum required pitch in bytes
0375  * @info: pixel format info
0376  * @plane: plane index
0377  * @buffer_width: buffer width in pixels
0378  *
0379  * Returns:
0380  * The minimum required pitch in bytes for a buffer by taking into consideration
0381  * the pixel format information and the buffer width.
0382  */
0383 uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
0384                    int plane, unsigned int buffer_width)
0385 {
0386     if (!info || plane < 0 || plane >= info->num_planes)
0387         return 0;
0388 
0389     return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
0390                 drm_format_info_block_width(info, plane) *
0391                 drm_format_info_block_height(info, plane));
0392 }
0393 EXPORT_SYMBOL(drm_format_info_min_pitch);