1/* $NetBSD: drm_fourcc.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $ */ 2 3/* 4 * Copyright (c) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com> 5 * 6 * DRM core format related functions 7 * 8 * Permission to use, copy, modify, distribute, and sell this software and its 9 * documentation for any purpose is hereby granted without fee, provided that 10 * the above copyright notice appear in all copies and that both that copyright 11 * notice and this permission notice appear in supporting documentation, and 12 * that the name of the copyright holders not be used in advertising or 13 * publicity pertaining to distribution of the software without specific, 14 * written prior permission. The copyright holders make no representations 15 * about the suitability of this software for any purpose. It is provided "as 16 * is" without express or implied warranty. 17 * 18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27#include <sys/cdefs.h> 28__KERNEL_RCSID(0, "$NetBSD: drm_fourcc.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $"); 29 30#include <linux/bug.h> 31#include <linux/ctype.h> 32#include <linux/export.h> 33#include <linux/kernel.h> 34 35#include <drm/drm_device.h> 36#include <drm/drm_fourcc.h> 37 38static char printable_char(int c) 39{ 40 return isascii(c) && isprint(c) ? c : '?'; 41} 42 43/** 44 * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description 45 * @bpp: bits per pixels 46 * @depth: bit depth per pixel 47 * 48 * Computes a drm fourcc pixel format code for the given @bpp/@depth values. 49 * Useful in fbdev emulation code, since that deals in those values. 50 */ 51uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) 52{ 53 uint32_t fmt = DRM_FORMAT_INVALID; 54 55 switch (bpp) { 56 case 8: 57 if (depth == 8) 58 fmt = DRM_FORMAT_C8; 59 break; 60 61 case 16: 62 switch (depth) { 63 case 15: 64 fmt = DRM_FORMAT_XRGB1555; 65 break; 66 case 16: 67 fmt = DRM_FORMAT_RGB565; 68 break; 69 default: 70 break; 71 } 72 break; 73 74 case 24: 75 if (depth == 24) 76 fmt = DRM_FORMAT_RGB888; 77 break; 78 79 case 32: 80 switch (depth) { 81 case 24: 82 fmt = DRM_FORMAT_XRGB8888; 83 break; 84 case 30: 85 fmt = DRM_FORMAT_XRGB2101010; 86 break; 87 case 32: 88 fmt = DRM_FORMAT_ARGB8888; 89 break; 90 default: 91 break; 92 } 93 break; 94 95 default: 96 break; 97 } 98 99 return fmt; 100} 101EXPORT_SYMBOL(drm_mode_legacy_fb_format); 102 103/** 104 * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description 105 * @dev: DRM device 106 * @bpp: bits per pixels 107 * @depth: bit depth per pixel 108 * 109 * Computes a drm fourcc pixel format code for the given @bpp/@depth values. 110 * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config, 111 * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag 112 * it returns little endian byte order or host byte order framebuffer formats. 113 */ 114uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, 115 uint32_t bpp, uint32_t depth) 116{ 117 uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth); 118 119 if (dev->mode_config.quirk_addfb_prefer_host_byte_order) { 120 if (fmt == DRM_FORMAT_XRGB8888) 121 fmt = DRM_FORMAT_HOST_XRGB8888; 122 if (fmt == DRM_FORMAT_ARGB8888) 123 fmt = DRM_FORMAT_HOST_ARGB8888; 124 if (fmt == DRM_FORMAT_RGB565) 125 fmt = DRM_FORMAT_HOST_RGB565; 126 if (fmt == DRM_FORMAT_XRGB1555) 127 fmt = DRM_FORMAT_HOST_XRGB1555; 128 } 129 130 if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && 131 fmt == DRM_FORMAT_XRGB2101010) 132 fmt = DRM_FORMAT_XBGR2101010; 133 134 return fmt; 135} 136EXPORT_SYMBOL(drm_driver_legacy_fb_format); 137 138/** 139 * drm_get_format_name - fill a string with a drm fourcc format's name 140 * @format: format to compute name of 141 * @buf: caller-supplied buffer 142 */ 143const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf) 144{ 145 snprintf(buf->str, sizeof(buf->str), 146 "%c%c%c%c %s-endian (0x%08x)", 147 printable_char(format & 0xff), 148 printable_char((format >> 8) & 0xff), 149 printable_char((format >> 16) & 0xff), 150 printable_char((format >> 24) & 0x7f), 151 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", 152 format); 153 154 return buf->str; 155} 156EXPORT_SYMBOL(drm_get_format_name); 157 158/* 159 * Internal function to query information for a given format. See 160 * drm_format_info() for the public API. 161 */ 162const struct drm_format_info *__drm_format_info(u32 format) 163{ 164 static const struct drm_format_info formats[] = { 165 { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, 166 { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, 167 { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, 168 { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 169 { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 170 { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 171 { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 172 { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 173 { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 174 { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 175 { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 176 { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 177 { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 178 { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 179 { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 180 { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 181 { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 182 { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 183 { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 184 { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 185 { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, 186 { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, 187 { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, 188 { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 189 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 190 { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 191 { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 192 { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 193 { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 194 { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 195 { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 196 { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 197 { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, 198 { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 199 { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 200 { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 201 { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 202 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 203 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 204 { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 205 { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 206 { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, 207 { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, 208 { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 209 { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 210 { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 211 { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 212 { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 213 { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 214 { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 215 { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, 216 { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, 217 { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, 218 { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, 219 { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, 220 { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, 221 { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, 222 { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 223 { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 224 { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 225 { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 226 { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, 227 { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, 228 { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 229 { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 230 { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 231 { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 232 { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 233 { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 234 { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 235 { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 236 { .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 237 { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 238 { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, 239 { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 240 { .format = DRM_FORMAT_Y212, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 241 { .format = DRM_FORMAT_Y216, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, 242 { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, 243 { .format = DRM_FORMAT_Y412, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, 244 { .format = DRM_FORMAT_Y416, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, 245 { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 246 { .format = DRM_FORMAT_XVYU12_16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 247 { .format = DRM_FORMAT_XVYU16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, 248 { .format = DRM_FORMAT_Y0L0, .depth = 0, .num_planes = 1, 249 .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, 250 .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, 251 { .format = DRM_FORMAT_X0L0, .depth = 0, .num_planes = 1, 252 .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, 253 .hsub = 2, .vsub = 2, .is_yuv = true }, 254 { .format = DRM_FORMAT_Y0L2, .depth = 0, .num_planes = 1, 255 .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, 256 .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, 257 { .format = DRM_FORMAT_X0L2, .depth = 0, .num_planes = 1, 258 .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, 259 .hsub = 2, .vsub = 2, .is_yuv = true }, 260 { .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, 261 .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, 262 .hsub = 2, .vsub = 2, .is_yuv = true}, 263 { .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, 264 .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, 265 .hsub = 2, .vsub = 2, .is_yuv = true}, 266 { .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, 267 .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, 268 .hsub = 2, .vsub = 2, .is_yuv = true}, 269 { .format = DRM_FORMAT_P210, .depth = 0, 270 .num_planes = 2, .char_per_block = { 2, 4, 0 }, 271 .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, 272 .vsub = 1, .is_yuv = true }, 273 { .format = DRM_FORMAT_VUY101010, .depth = 0, 274 .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1, 275 .is_yuv = true }, 276 { .format = DRM_FORMAT_YUV420_8BIT, .depth = 0, 277 .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, 278 .is_yuv = true }, 279 { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, 280 .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, 281 .is_yuv = true }, 282 }; 283 284 unsigned int i; 285 286 for (i = 0; i < ARRAY_SIZE(formats); ++i) { 287 if (formats[i].format == format) 288 return &formats[i]; 289 } 290 291 return NULL; 292} 293 294/** 295 * drm_format_info - query information for a given format 296 * @format: pixel format (DRM_FORMAT_*) 297 * 298 * The caller should only pass a supported pixel format to this function. 299 * Unsupported pixel formats will generate a warning in the kernel log. 300 * 301 * Returns: 302 * The instance of struct drm_format_info that describes the pixel format, or 303 * NULL if the format is unsupported. 304 */ 305const struct drm_format_info *drm_format_info(u32 format) 306{ 307 const struct drm_format_info *info; 308 309 info = __drm_format_info(format); 310 WARN_ON(!info); 311 return info; 312} 313EXPORT_SYMBOL(drm_format_info); 314 315/** 316 * drm_get_format_info - query information for a given framebuffer configuration 317 * @dev: DRM device 318 * @mode_cmd: metadata from the userspace fb creation request 319 * 320 * Returns: 321 * The instance of struct drm_format_info that describes the pixel format, or 322 * NULL if the format is unsupported. 323 */ 324const struct drm_format_info * 325drm_get_format_info(struct drm_device *dev, 326 const struct drm_mode_fb_cmd2 *mode_cmd) 327{ 328 const struct drm_format_info *info = NULL; 329 330 if (dev->mode_config.funcs->get_format_info) 331 info = dev->mode_config.funcs->get_format_info(mode_cmd); 332 333 if (!info) 334 info = drm_format_info(mode_cmd->pixel_format); 335 336 return info; 337} 338EXPORT_SYMBOL(drm_get_format_info); 339 340/** 341 * drm_format_info_block_width - width in pixels of block. 342 * @info: pixel format info 343 * @plane: plane index 344 * 345 * Returns: 346 * The width in pixels of a block, depending on the plane index. 347 */ 348unsigned int drm_format_info_block_width(const struct drm_format_info *info, 349 int plane) 350{ 351 if (!info || plane < 0 || plane >= info->num_planes) 352 return 0; 353 354 if (!info->block_w[plane]) 355 return 1; 356 return info->block_w[plane]; 357} 358EXPORT_SYMBOL(drm_format_info_block_width); 359 360/** 361 * drm_format_info_block_height - height in pixels of a block 362 * @info: pixel format info 363 * @plane: plane index 364 * 365 * Returns: 366 * The height in pixels of a block, depending on the plane index. 367 */ 368unsigned int drm_format_info_block_height(const struct drm_format_info *info, 369 int plane) 370{ 371 if (!info || plane < 0 || plane >= info->num_planes) 372 return 0; 373 374 if (!info->block_h[plane]) 375 return 1; 376 return info->block_h[plane]; 377} 378EXPORT_SYMBOL(drm_format_info_block_height); 379 380/** 381 * drm_format_info_min_pitch - computes the minimum required pitch in bytes 382 * @info: pixel format info 383 * @plane: plane index 384 * @buffer_width: buffer width in pixels 385 * 386 * Returns: 387 * The minimum required pitch in bytes for a buffer by taking into consideration 388 * the pixel format information and the buffer width. 389 */ 390uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, 391 int plane, unsigned int buffer_width) 392{ 393 if (!info || plane < 0 || plane >= info->num_planes) 394 return 0; 395 396 return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane], 397 drm_format_info_block_width(info, plane) * 398 drm_format_info_block_height(info, plane)); 399} 400EXPORT_SYMBOL(drm_format_info_min_pitch); 401