drm_format_horz_chroma_subsampling and drm_format_vert_chroma_subsampling are basically a lookup in the drm_format_info table plus an access to the hsub and vsub fields of the appropriate entry. Most drivers are using this function while having access to the entry already, which means that we will perform an unnecessary lookup. Removing the call to these functions is therefore more efficient. Some drivers will not have access to that entry in the function, but in this case the overhead is minimal (we just have to call drm_format_info() to perform the lookup) and we can even avoid multiple, inefficient lookups in some places that need multiple fields from the drm_format_info structure. This is amplified by the fact that most of the time the callers will have to retrieve both the vsub and hsub fields, meaning that they would perform twice the lookup. Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://patchwork.freedesktop.org/patch/msgid/6b3cceb8161e2c1d40c2681de99202328b0a8abc.1558002671.git-series.maxime.ripard@bootlin.com
464 lines
21 KiB
C
464 lines
21 KiB
C
/*
|
|
* 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/drmP.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 8:
|
|
if (depth == 8)
|
|
fmt = DRM_FORMAT_C8;
|
|
break;
|
|
|
|
case 16:
|
|
switch (depth) {
|
|
case 15:
|
|
fmt = DRM_FORMAT_XRGB1555;
|
|
break;
|
|
case 16:
|
|
fmt = DRM_FORMAT_RGB565;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
if (depth == 24)
|
|
fmt = DRM_FORMAT_RGB888;
|
|
break;
|
|
|
|
case 32:
|
|
switch (depth) {
|
|
case 24:
|
|
fmt = DRM_FORMAT_XRGB8888;
|
|
break;
|
|
case 30:
|
|
fmt = DRM_FORMAT_XRGB2101010;
|
|
break;
|
|
case 32:
|
|
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)
|
|
{
|
|
snprintf(buf->str, sizeof(buf->str),
|
|
"%c%c%c%c %s-endian (0x%08x)",
|
|
printable_char(format & 0xff),
|
|
printable_char((format >> 8) & 0xff),
|
|
printable_char((format >> 16) & 0xff),
|
|
printable_char((format >> 24) & 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, 0, 0 }, .block_h = { 1, 0, 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, 0, 0 }, .block_h = { 1, 0, 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, 0, 0 }, .block_h = { 1, 0, 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, 0, 0 }, .block_h = { 1, 0, 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 },
|
|
};
|
|
|
|
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_plane_cpp - determine the bytes per pixel value
|
|
* @format: pixel format (DRM_FORMAT_*)
|
|
* @plane: plane index
|
|
*
|
|
* Returns:
|
|
* The bytes per pixel value for the specified plane.
|
|
*/
|
|
int drm_format_plane_cpp(uint32_t format, int plane)
|
|
{
|
|
const struct drm_format_info *info;
|
|
|
|
info = drm_format_info(format);
|
|
if (!info || plane >= info->num_planes)
|
|
return 0;
|
|
|
|
return info->cpp[plane];
|
|
}
|
|
EXPORT_SYMBOL(drm_format_plane_cpp);
|
|
|
|
/**
|
|
* drm_format_plane_width - width of the plane given the first plane
|
|
* @width: width of the first plane
|
|
* @format: pixel format
|
|
* @plane: plane index
|
|
*
|
|
* Returns:
|
|
* The width of @plane, given that the width of the first plane is @width.
|
|
*/
|
|
int drm_format_plane_width(int width, uint32_t format, int plane)
|
|
{
|
|
const struct drm_format_info *info;
|
|
|
|
info = drm_format_info(format);
|
|
if (!info || plane >= info->num_planes)
|
|
return 0;
|
|
|
|
if (plane == 0)
|
|
return width;
|
|
|
|
return width / info->hsub;
|
|
}
|
|
EXPORT_SYMBOL(drm_format_plane_width);
|
|
|
|
/**
|
|
* drm_format_plane_height - height of the plane given the first plane
|
|
* @height: height of the first plane
|
|
* @format: pixel format
|
|
* @plane: plane index
|
|
*
|
|
* Returns:
|
|
* The height of @plane, given that the height of the first plane is @height.
|
|
*/
|
|
int drm_format_plane_height(int height, uint32_t format, int plane)
|
|
{
|
|
const struct drm_format_info *info;
|
|
|
|
info = drm_format_info(format);
|
|
if (!info || plane >= info->num_planes)
|
|
return 0;
|
|
|
|
if (plane == 0)
|
|
return height;
|
|
|
|
return height / info->vsub;
|
|
}
|
|
EXPORT_SYMBOL(drm_format_plane_height);
|
|
|
|
/**
|
|
* 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);
|