* Copyright (c) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
* DRM core format related functions
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <linux/bug.h>
#include <linux/ctype.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <drm/drm_device.h>
#include <drm/drm_fourcc.h>
static char printable_char(int c)
{
return isascii(c) && isprint(c) ? c : '?';
}
* drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
* @bpp: bits per pixels
* @depth: bit depth per pixel
*
* Computes a drm fourcc pixel format code for the given @bpp/@depth values.
* Useful in fbdev emulation code, since that deals in those values.
*/
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
{
uint32_t fmt = DRM_FORMAT_INVALID;
switch (bpp) {
case 0x8:
if (depth == 0x8) {
fmt = DRM_FORMAT_C8;
}
break;
case 0x10:
switch (depth) {
case 0xf:
fmt = DRM_FORMAT_XRGB1555;
break;
case 0x10:
fmt = DRM_FORMAT_RGB565;
break;
default:
break;
}
break;
case 0x18:
if (depth == 0x18) {
fmt = DRM_FORMAT_RGB888;
}
break;
case 0x20:
switch (depth) {
case 0x18:
fmt = DRM_FORMAT_XRGB8888;
break;
case 0x1e:
fmt = DRM_FORMAT_XRGB2101010;
break;
case 0x20:
fmt = DRM_FORMAT_ARGB8888;
break;
default:
break;
}
break;
default:
break;
}
return fmt;
}
EXPORT_SYMBOL(drm_mode_legacy_fb_format);
* drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
* @dev: DRM device
* @bpp: bits per pixels
* @depth: bit depth per pixel
*
* Computes a drm fourcc pixel format code for the given @bpp/@depth values.
* Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
* and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag
* it returns little endian byte order or host byte order framebuffer formats.
*/
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth)
{
uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth);
if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
if (fmt == DRM_FORMAT_XRGB8888) {
fmt = DRM_FORMAT_HOST_XRGB8888;
}
if (fmt == DRM_FORMAT_ARGB8888) {
fmt = DRM_FORMAT_HOST_ARGB8888;
}
if (fmt == DRM_FORMAT_RGB565) {
fmt = DRM_FORMAT_HOST_RGB565;
}
if (fmt == DRM_FORMAT_XRGB1555) {
fmt = DRM_FORMAT_HOST_XRGB1555;
}
}
if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && fmt == DRM_FORMAT_XRGB2101010) {
fmt = DRM_FORMAT_XBGR2101010;
}
return fmt;
}
EXPORT_SYMBOL(drm_driver_legacy_fb_format);
* drm_get_format_name - fill a string with a drm fourcc format's name
* @format: format to compute name of
* @buf: caller-supplied buffer
*/
const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
{
int ret = 0;
ret = snprintf(buf->str, sizeof(buf->str), "%c%c%c%c %s-endian (0x%08x)", printable_char(format & 0xff),
printable_char((format >> 0x8) & 0xff), printable_char((format >> 0x10) & 0xff),
printable_char((format >> 0x18) & 0x7f), format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", format);
return buf->str;
}
EXPORT_SYMBOL(drm_get_format_name);
* Internal function to query information for a given format. See
* drm_format_info() for the public API.
*/
const struct drm_format_info *__drm_format_info(u32 format)
{
static const struct drm_format_info formats[] = {
{.format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_ARGB4444,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ABGR4444,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGBA4444,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGRA4444,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_ARGB1555,
.depth = 15,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ABGR1555,
.depth = 15,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGBA5551,
.depth = 15,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGRA5551,
.depth = 15,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = {3, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = {3, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGB565_A8,
.depth = 24,
.num_planes = 2,
.cpp = {2, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGR565_A8,
.depth = 24,
.num_planes = 2,
.cpp = {2, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_ARGB2101010,
.depth = 30,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ABGR2101010,
.depth = 30,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGBA1010102,
.depth = 30,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGRA1010102,
.depth = 30,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ARGB8888,
.depth = 32,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ABGR8888,
.depth = 32,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGBA8888,
.depth = 32,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGRA8888,
.depth = 32,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = {8, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = {8, 0, 0}, .hsub = 1, .vsub = 1},
{.format = DRM_FORMAT_ARGB16161616F,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_ABGR16161616F,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGB888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {3, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGR888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {3, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_XRGB8888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {4, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_XBGR8888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {4, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_RGBX8888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {4, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_BGRX8888_A8,
.depth = 32,
.num_planes = 2,
.cpp = {4, 1, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true},
{.format = DRM_FORMAT_YUV410,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 4,
.vsub = 4,
.is_yuv = true},
{.format = DRM_FORMAT_YVU410,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 4,
.vsub = 4,
.is_yuv = true},
{.format = DRM_FORMAT_YUV411,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 4,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YVU411,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 4,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YUV420,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_YVU420,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_YUV422,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YVU422,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YUV444,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YVU444,
.depth = 0,
.num_planes = 3,
.cpp = {1, 1, 1},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_NV12,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_NV21,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_NV16,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_NV61,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_NV24,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_NV42,
.depth = 0,
.num_planes = 2,
.cpp = {1, 2, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YUYV,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YVYU,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_UYVY,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_VYUY,
.depth = 0,
.num_planes = 1,
.cpp = {2, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_XYUV8888,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_VUY888,
.depth = 0,
.num_planes = 1,
.cpp = {3, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_AYUV,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_Y210,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_Y212,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_Y216,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_Y410,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_Y412,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_Y416,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_XVYU2101010,
.depth = 0,
.num_planes = 1,
.cpp = {4, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_XVYU12_16161616,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_XVYU16161616,
.depth = 0,
.num_planes = 1,
.cpp = {8, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_Y0L0,
.depth = 0,
.num_planes = 1,
.char_per_block = {8, 0, 0},
.block_w = {2, 0, 0},
.block_h = {2, 0, 0},
.hsub = 2,
.vsub = 2,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_X0L0,
.depth = 0,
.num_planes = 1,
.char_per_block = {8, 0, 0},
.block_w = {2, 0, 0},
.block_h = {2, 0, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_Y0L2,
.depth = 0,
.num_planes = 1,
.char_per_block = {8, 0, 0},
.block_w = {2, 0, 0},
.block_h = {2, 0, 0},
.hsub = 2,
.vsub = 2,
.has_alpha = true,
.is_yuv = true},
{.format = DRM_FORMAT_X0L2,
.depth = 0,
.num_planes = 1,
.char_per_block = {8, 0, 0},
.block_w = {2, 0, 0},
.block_h = {2, 0, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_P010,
.depth = 0,
.num_planes = 2,
.char_per_block = {2, 4, 0},
.block_w = {1, 1, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_P012,
.depth = 0,
.num_planes = 2,
.char_per_block = {2, 4, 0},
.block_w = {1, 1, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_P016,
.depth = 0,
.num_planes = 2,
.char_per_block = {2, 4, 0},
.block_w = {1, 1, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_P210,
.depth = 0,
.num_planes = 2,
.char_per_block = {2, 4, 0},
.block_w = {1, 1, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_VUY101010,
.depth = 0,
.num_planes = 1,
.cpp = {0, 0, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_YUV420_8BIT,
.depth = 0,
.num_planes = 1,
.cpp = {0, 0, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_YUV420_10BIT,
.depth = 0,
.num_planes = 1,
.cpp = {0, 0, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
{.format = DRM_FORMAT_NV15,
.depth = 0,
.num_planes = 2,
.char_per_block = {5, 5, 0},
.block_w = {4, 2, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 2,
.is_yuv = true},
#ifdef CONFIG_NO_GKI
{.format = DRM_FORMAT_NV20,
.depth = 0,
.num_planes = 2,
.char_per_block = {5, 5, 0},
.block_w = {4, 2, 0},
.block_h = {1, 1, 0},
.hsub = 2,
.vsub = 1,
.is_yuv = true},
{.format = DRM_FORMAT_NV30,
.depth = 0,
.num_planes = 2,
.char_per_block = {5, 5, 0},
.block_w = {4, 2, 0},
.block_h = {1, 1, 0},
.hsub = 1,
.vsub = 1,
.is_yuv = true},
#endif
{.format = DRM_FORMAT_Q410,
.depth = 0,
.num_planes = 3,
.char_per_block = {2, 2, 2},
.block_w = {1, 1, 1},
.block_h = {1, 1, 1},
.hsub = 0,
.vsub = 0,
.is_yuv = true},
{.format = DRM_FORMAT_Q401,
.depth = 0,
.num_planes = 3,
.char_per_block = {2, 2, 2},
.block_w = {1, 1, 1},
.block_h = {1, 1, 1},
.hsub = 0,
.vsub = 0,
.is_yuv = true},
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
if (formats[i].format == format) {
return &formats[i];
}
}
return NULL;
}
* drm_format_info - query information for a given format
* @format: pixel format (DRM_FORMAT_*)
*
* The caller should only pass a supported pixel format to this function.
* Unsupported pixel formats will generate a warning in the kernel log.
*
* Returns:
* The instance of struct drm_format_info that describes the pixel format, or
* NULL if the format is unsupported.
*/
const struct drm_format_info *drm_format_info(u32 format)
{
const struct drm_format_info *info;
info = __drm_format_info(format);
WARN_ON(!info);
return info;
}
EXPORT_SYMBOL(drm_format_info);
* drm_get_format_info - query information for a given framebuffer configuration
* @dev: DRM device
* @mode_cmd: metadata from the userspace fb creation request
*
* Returns:
* The instance of struct drm_format_info that describes the pixel format, or
* NULL if the format is unsupported.
*/
const struct drm_format_info *drm_get_format_info(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd)
{
const struct drm_format_info *info = NULL;
if (dev->mode_config.funcs->get_format_info) {
info = dev->mode_config.funcs->get_format_info(mode_cmd);
}
if (!info) {
info = drm_format_info(mode_cmd->pixel_format);
}
return info;
}
EXPORT_SYMBOL(drm_get_format_info);
* drm_format_info_block_width - width in pixels of block.
* @info: pixel format info
* @plane: plane index
*
* Returns:
* The width in pixels of a block, depending on the plane index.
*/
unsigned int drm_format_info_block_width(const struct drm_format_info *info, int plane)
{
if (!info || plane < 0 || plane >= info->num_planes) {
return 0;
}
if (!info->block_w[plane]) {
return 1;
}
return info->block_w[plane];
}
EXPORT_SYMBOL(drm_format_info_block_width);
* drm_format_info_block_height - height in pixels of a block
* @info: pixel format info
* @plane: plane index
*
* Returns:
* The height in pixels of a block, depending on the plane index.
*/
unsigned int drm_format_info_block_height(const struct drm_format_info *info, int plane)
{
if (!info || plane < 0 || plane >= info->num_planes) {
return 0;
}
if (!info->block_h[plane]) {
return 1;
}
return info->block_h[plane];
}
EXPORT_SYMBOL(drm_format_info_block_height);
* drm_format_info_min_pitch - computes the minimum required pitch in bytes
* @info: pixel format info
* @plane: plane index
* @buffer_width: buffer width in pixels
*
* Returns:
* The minimum required pitch in bytes for a buffer by taking into consideration
* the pixel format information and the buffer width.
*/
uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, int plane, unsigned int buffer_width)
{
if (!info || plane < 0 || plane >= info->num_planes) {
return 0;
}
return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
drm_format_info_block_width(info, plane) * drm_format_info_block_height(info, plane));
}
EXPORT_SYMBOL(drm_format_info_min_pitch);