2016-06-09 17:54:08 +08:00
|
|
|
/*
|
|
|
|
* 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 : '?';
|
|
|
|
}
|
|
|
|
|
2016-08-29 16:27:54 +08:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2018-09-05 23:31:16 +08:00
|
|
|
uint32_t fmt = DRM_FORMAT_INVALID;
|
2016-08-29 16:27:54 +08:00
|
|
|
|
|
|
|
switch (bpp) {
|
|
|
|
case 8:
|
2018-09-05 23:31:16 +08:00
|
|
|
if (depth == 8)
|
|
|
|
fmt = DRM_FORMAT_C8;
|
2016-08-29 16:27:54 +08:00
|
|
|
break;
|
2018-09-05 23:31:16 +08:00
|
|
|
|
2016-08-29 16:27:54 +08:00
|
|
|
case 16:
|
2018-09-05 23:31:16 +08:00
|
|
|
switch (depth) {
|
|
|
|
case 15:
|
2016-08-29 16:27:54 +08:00
|
|
|
fmt = DRM_FORMAT_XRGB1555;
|
2018-09-05 23:31:16 +08:00
|
|
|
break;
|
|
|
|
case 16:
|
2016-08-29 16:27:54 +08:00
|
|
|
fmt = DRM_FORMAT_RGB565;
|
2018-09-05 23:31:16 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-08-29 16:27:54 +08:00
|
|
|
break;
|
2018-09-05 23:31:16 +08:00
|
|
|
|
2016-08-29 16:27:54 +08:00
|
|
|
case 24:
|
2018-09-05 23:31:16 +08:00
|
|
|
if (depth == 24)
|
|
|
|
fmt = DRM_FORMAT_RGB888;
|
2016-08-29 16:27:54 +08:00
|
|
|
break;
|
2018-09-05 23:31:16 +08:00
|
|
|
|
2016-08-29 16:27:54 +08:00
|
|
|
case 32:
|
2018-09-05 23:31:16 +08:00
|
|
|
switch (depth) {
|
|
|
|
case 24:
|
2016-08-29 16:27:54 +08:00
|
|
|
fmt = DRM_FORMAT_XRGB8888;
|
2018-09-05 23:31:16 +08:00
|
|
|
break;
|
|
|
|
case 30:
|
2016-08-29 16:27:54 +08:00
|
|
|
fmt = DRM_FORMAT_XRGB2101010;
|
2018-09-05 23:31:16 +08:00
|
|
|
break;
|
|
|
|
case 32:
|
2016-08-29 16:27:54 +08:00
|
|
|
fmt = DRM_FORMAT_ARGB8888;
|
2018-09-05 23:31:16 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-08-29 16:27:54 +08:00
|
|
|
break;
|
2018-09-05 23:31:16 +08:00
|
|
|
|
2016-08-29 16:27:54 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_mode_legacy_fb_format);
|
|
|
|
|
2018-09-21 21:46:59 +08:00
|
|
|
/**
|
|
|
|
* drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
|
2018-10-05 04:24:44 +08:00
|
|
|
* @dev: DRM device
|
2018-09-21 21:46:59 +08:00
|
|
|
* @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,
|
2018-10-05 04:24:44 +08:00
|
|
|
* 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.
|
2018-09-21 21:46:59 +08:00
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
2018-09-21 21:47:04 +08:00
|
|
|
|
|
|
|
if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
|
|
|
|
fmt == DRM_FORMAT_XRGB2101010)
|
|
|
|
fmt = DRM_FORMAT_XBGR2101010;
|
|
|
|
|
2018-09-21 21:46:59 +08:00
|
|
|
return fmt;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_driver_legacy_fb_format);
|
|
|
|
|
2016-06-09 17:54:08 +08:00
|
|
|
/**
|
2016-11-12 09:12:56 +08:00
|
|
|
* drm_get_format_name - fill a string with a drm fourcc format's name
|
2016-06-09 17:54:08 +08:00
|
|
|
* @format: format to compute name of
|
2016-11-12 09:12:56 +08:00
|
|
|
* @buf: caller-supplied buffer
|
2016-06-09 17:54:08 +08:00
|
|
|
*/
|
2016-11-12 09:12:56 +08:00
|
|
|
const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
|
2016-06-09 17:54:08 +08:00
|
|
|
{
|
2016-11-12 09:12:56 +08:00
|
|
|
snprintf(buf->str, sizeof(buf->str),
|
2016-06-09 17:54:08 +08:00
|
|
|
"%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);
|
|
|
|
|
2016-11-12 09:12:56 +08:00
|
|
|
return buf->str;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_get_format_name);
|
|
|
|
|
2016-10-18 06:41:12 +08:00
|
|
|
/*
|
|
|
|
* Internal function to query information for a given format. See
|
|
|
|
* drm_format_info() for the public API.
|
2016-10-18 06:41:09 +08:00
|
|
|
*/
|
2016-10-18 06:41:12 +08:00
|
|
|
const struct drm_format_info *__drm_format_info(u32 format)
|
2016-10-18 06:41:09 +08:00
|
|
|
{
|
|
|
|
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 },
|
2017-12-22 22:29:26 +08:00
|
|
|
{ .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 },
|
2016-10-18 06:41:09 +08:00
|
|
|
{ .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 },
|
2017-12-22 22:29:26 +08:00
|
|
|
{ .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 },
|
2016-10-18 06:41:09 +08:00
|
|
|
{ .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 },
|
2017-12-22 22:29:26 +08:00
|
|
|
{ .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 },
|
2016-10-18 06:41:09 +08:00
|
|
|
{ .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 },
|
2017-12-22 22:29:26 +08:00
|
|
|
{ .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_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 },
|
2018-07-18 01:13:42 +08:00
|
|
|
{ .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 },
|
2018-11-09 17:39:15 +08:00
|
|
|
{ .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
|
drm/fourcc: Add AFBC yuv fourccs for Mali
As we look to enable AFBC using DRM format modifiers, we run into
problems which we've historically handled via vendor-private details
(i.e. gralloc, on Android).
AFBC (as an encoding) is fully flexible, and for example YUV data can
be encoded into 1, 2 or 3 encoded "planes", much like the linear
equivalents. Component order is also meaningful, as AFBC doesn't
necessarily care about what each "channel" of the data it encodes
contains. Therefore ABGR8888 and RGBA8888 can be encoded in AFBC with
different representations. Similarly, 'X' components may be encoded
into AFBC streams in cases where a decoder expects to decode a 4th
component.
In addition, AFBC is a licensable IP, meaning that to support the
ecosystem we need to ensure that _all_ AFBC users are able to describe
the encodings that they need. This is much better achieved by
preserving meaning in the fourcc codes when they are combined with an
AFBC modifier.
In essence, we want to use the modifier to describe the parameters of
the AFBC encode/decode, and use the fourcc code to describe the data
being encoded/decoded.
To do anything different would be to introduce redundancy - we would
need to duplicate in the modifier information which is _already_
conveyed clearly and non-ambigiously by a fourcc code.
I hope that for RGB this is non-controversial.
(BGRA8888 + MODIFIER_AFBC) is a different format from
(RGBA8888 + MODIFIER_AFBC).
Possibly more controversial is that (XBGR8888 + MODIFIER_AFBC)
is different from (BGR888 + MODIFIER_AFBC). I understand that in some
schemes it is not the case - but in AFBC it is so.
Where we run into problems is where there are not already fourcc codes
which represent the data which the AFBC encoder/decoder is processing.
To that end, we want to introduce new fourcc codes to describe the
data being encoded/decoded, in the places where none of the existing
fourcc codes are applicable.
Where we don't support an equivalent non-compressed layout, or where
no "obvious" linear layout exists, we are proposing adding fourcc
codes which have no associated linear layout - because any layout we
proposed would be completely arbitrary.
Some formats are following the naming conventions from [2].
The summary of the new formats is:
DRM_FORMAT_VUY888 - Packed 8-bit YUV 444. Y followed by U then V.
DRM_FORMAT_VUY101010 - Packed 10-bit YUV 444. Y followed by U then
V. No defined linear encoding.
DRM_FORMAT_Y210 - Packed 10-bit YUV 422. Y followed by U (then Y)
then V. 10-bit samples in 16-bit words.
DRM_FORMAT_Y410 - Packed 10-bit YUV 444, with 2-bit alpha.
DRM_FORMAT_P210 - Semi-planar 10-bit YUV 422. Y plane, followed by
interleaved U-then-V plane. 10-bit samples in
16-bit words.
DRM_FORMAT_YUV420_8BIT - Packed 8-bit YUV 420. Y followed by U then
V. No defined linear encoding
DRM_FORMAT_YUV420_10BIT - Packed 10-bit YUV 420. Y followed by U
then V. No defined linear encoding
Please also note that in the absence of AFBC, we would still need to
add Y410, Y210 and P210.
Full rationale follows:
YUV 444 8-bit, 1-plane
----------------------
The currently defined AYUV format encodes a 4th alpha component,
which makes it unsuitable for representing a 3-component YUV 444
AFBC stream.
The proposed[1] XYUV format which is supported by Mali-DP in linear
layout is also unsuitable, because the component order is the
opposite of the AFBC version, and it encodes a 4th 'X' component.
DRM_FORMAT_VUY888 is the "obvious" format for a 3-component, packed,
YUV 444 8-bit format, with the component order which our HW expects to
encode/decode. It conforms to the same naming convention as the
existing packed YUV 444 format.
The naming here is meant to be consistent with DRM_FORMAT_AYUV and
DRM_FORMAT_XYUV[1]
YUV 444 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 444 10-bit format in
drm_fourcc.h, irrespective of number of planes.
The proposed[1] XVYU2101010 format which is supported by Mali-DP in
linear layout uses the wrong component order, and also encodes a 4th
'X' component, which doesn't match the AFBC version of YUV 444
10-bit which we support.
DRM_FORMAT_Y410 is the same layout as XVYU2101010, but with 2 bits of
alpha. This format is supported with linear layout by Mali GPUs. The
naming follows[2].
There is no "obvious" linear encoding for a 3-component 10:10:10
packed format, and so DRM_FORMAT_VUY101010 defines a component
order, but not a bit encoding. Again, the naming is meant to be
consistent with DRM_FORMAT_AYUV.
YUV 422 8-bit, 1-plane
----------------------
The existing DRM_FORMAT_YUYV (and the other component orders) are
single-planar YUV 422 8-bit formats. Following the convention of
the component orders of the RGB formats, YUYV has the correct
component order for our AFBC encoding (Y followed by U followed by
V). We can use YUYV for AFBC YUV 422 8-bit.
YUV 422 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 422 10-bit format in drm_fourcc.h
DRM_FORMAT_Y210 is analogous to YUYV, but with 10-bits per sample
packed into the upper 10-bits of 16-bit samples. This format is
supported in both linear and AFBC by Mali GPUs.
YUV 422 10-bit, 2-plane
-----------------------
The recently defined DRM_FORMAT_P010 format is a 10-bit semi-planar
YUV 420 format, which has the correct component ordering for an AFBC
2-plane YUV 420 buffer. The linear layout contains meaningless padding
bits, which will not be encoded in an AFBC stream.
YUV 420 8-bit, 1-plane
----------------------
There is no currently defined single-planar YUV 420, 8-bit format
in drm_fourcc.h. There's differing opinions on whether using the
existing fourcc-implied n_planes where possible is a good idea or
not when using modifiers.
For me, it's much more "obvious" to use NV12 for 2-plane AFBC and
YUV420 for 3-plane AFBC. This keeps the aforementioned separation
between the AFBC codec settings (in the modifier) and the pixel data
format (in the fourcc). With different vendors using AFBC, this helps
to ensure that there is no confusion in interoperation. It also
ensures that the AFBC modifiers describe AFBC itself (which is a
licensable component), and not implementation details which are not
defined by AFBC.
The proposed[1] X0L0 format which Mali-DP supports with Linear layout
is unsuitable, as it contains a 4th 'X' component, and our AFBC
decoder expects only 3 components.
To that end, we propose a new YUV 420 8-bit format. There is no
"obvious" linear encoding for a 3-component 8:8:8, 420, packed format,
and so DRM_FORMAT_YUV420_8BIT defines a component order, but not a
bit encoding. I'm happy to hear different naming suggestions.
YUV 420 8-bit, 2-, 3-plane
--------------------------
These already exist, we can use NV12 and YUV420.
YUV 420 10-bit, 1-plane
-----------------------
As above, no current definition exists, and X0L2 encodes a 4th 'X'
channel.
Analogous to DRM_FORMAT_YUV420_8BIT, we define DRM_FORMAT_YUV420_10BIT.
[1] https://lists.freedesktop.org/archives/dri-devel/2018-July/184598.html
[2] https://docs.microsoft.com/en-us/windows/desktop/medfound/10-bit-and-16-bit-yuv-video-formats
Changes since RFC v1:
- Fix confusing subsampling vs bit-depth X:X:X notation in
descriptions (danvet)
- Rename DRM_FORMAT_AVYU1101010 to DRM_FORMAT_Y410 (Lisa Wu)
- Add drm_format_info structures for the new formats, using the
new 'bpp' field for those with non-integer bytes-per-pixel
- Rebase, including Juha-Pekka Heikkila's format definitions
Changes since RFC v2:
- Rebase on top of latest changes in drm-misc-next
- Change the description of DRM_FORMAT_P210 in __drm_format_info and
drm_fourcc.h so as to make it consistent with other DRM_FORMAT_PXXX
formats.
Changes since v3:
- Added the ack
- Rebased on the latest drm-misc-next
Signed-off-by: Brian Starkey <brian.starkey@arm.com>
Signed-off-by: Ayan Kumar Halder <ayan.halder@arm.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Link: https://patchwork.freedesktop.org/patch/291759/?series=57895&rev=1
2018-10-05 17:27:00 +08:00
|
|
|
{ .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .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_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
|
2018-07-18 01:13:42 +08:00
|
|
|
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
|
2018-11-10 01:21:12 +08:00
|
|
|
{ .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
|
2019-03-04 19:56:33 +08:00
|
|
|
{ .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, .is_yuv = true },
|
|
|
|
{ .format = DRM_FORMAT_Y412, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
|
|
|
|
{ .format = DRM_FORMAT_Y416, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
|
2018-11-01 23:11:30 +08:00
|
|
|
{ .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 },
|
2019-01-10 03:57:09 +08:00
|
|
|
{ .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},
|
drm/fourcc: Add AFBC yuv fourccs for Mali
As we look to enable AFBC using DRM format modifiers, we run into
problems which we've historically handled via vendor-private details
(i.e. gralloc, on Android).
AFBC (as an encoding) is fully flexible, and for example YUV data can
be encoded into 1, 2 or 3 encoded "planes", much like the linear
equivalents. Component order is also meaningful, as AFBC doesn't
necessarily care about what each "channel" of the data it encodes
contains. Therefore ABGR8888 and RGBA8888 can be encoded in AFBC with
different representations. Similarly, 'X' components may be encoded
into AFBC streams in cases where a decoder expects to decode a 4th
component.
In addition, AFBC is a licensable IP, meaning that to support the
ecosystem we need to ensure that _all_ AFBC users are able to describe
the encodings that they need. This is much better achieved by
preserving meaning in the fourcc codes when they are combined with an
AFBC modifier.
In essence, we want to use the modifier to describe the parameters of
the AFBC encode/decode, and use the fourcc code to describe the data
being encoded/decoded.
To do anything different would be to introduce redundancy - we would
need to duplicate in the modifier information which is _already_
conveyed clearly and non-ambigiously by a fourcc code.
I hope that for RGB this is non-controversial.
(BGRA8888 + MODIFIER_AFBC) is a different format from
(RGBA8888 + MODIFIER_AFBC).
Possibly more controversial is that (XBGR8888 + MODIFIER_AFBC)
is different from (BGR888 + MODIFIER_AFBC). I understand that in some
schemes it is not the case - but in AFBC it is so.
Where we run into problems is where there are not already fourcc codes
which represent the data which the AFBC encoder/decoder is processing.
To that end, we want to introduce new fourcc codes to describe the
data being encoded/decoded, in the places where none of the existing
fourcc codes are applicable.
Where we don't support an equivalent non-compressed layout, or where
no "obvious" linear layout exists, we are proposing adding fourcc
codes which have no associated linear layout - because any layout we
proposed would be completely arbitrary.
Some formats are following the naming conventions from [2].
The summary of the new formats is:
DRM_FORMAT_VUY888 - Packed 8-bit YUV 444. Y followed by U then V.
DRM_FORMAT_VUY101010 - Packed 10-bit YUV 444. Y followed by U then
V. No defined linear encoding.
DRM_FORMAT_Y210 - Packed 10-bit YUV 422. Y followed by U (then Y)
then V. 10-bit samples in 16-bit words.
DRM_FORMAT_Y410 - Packed 10-bit YUV 444, with 2-bit alpha.
DRM_FORMAT_P210 - Semi-planar 10-bit YUV 422. Y plane, followed by
interleaved U-then-V plane. 10-bit samples in
16-bit words.
DRM_FORMAT_YUV420_8BIT - Packed 8-bit YUV 420. Y followed by U then
V. No defined linear encoding
DRM_FORMAT_YUV420_10BIT - Packed 10-bit YUV 420. Y followed by U
then V. No defined linear encoding
Please also note that in the absence of AFBC, we would still need to
add Y410, Y210 and P210.
Full rationale follows:
YUV 444 8-bit, 1-plane
----------------------
The currently defined AYUV format encodes a 4th alpha component,
which makes it unsuitable for representing a 3-component YUV 444
AFBC stream.
The proposed[1] XYUV format which is supported by Mali-DP in linear
layout is also unsuitable, because the component order is the
opposite of the AFBC version, and it encodes a 4th 'X' component.
DRM_FORMAT_VUY888 is the "obvious" format for a 3-component, packed,
YUV 444 8-bit format, with the component order which our HW expects to
encode/decode. It conforms to the same naming convention as the
existing packed YUV 444 format.
The naming here is meant to be consistent with DRM_FORMAT_AYUV and
DRM_FORMAT_XYUV[1]
YUV 444 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 444 10-bit format in
drm_fourcc.h, irrespective of number of planes.
The proposed[1] XVYU2101010 format which is supported by Mali-DP in
linear layout uses the wrong component order, and also encodes a 4th
'X' component, which doesn't match the AFBC version of YUV 444
10-bit which we support.
DRM_FORMAT_Y410 is the same layout as XVYU2101010, but with 2 bits of
alpha. This format is supported with linear layout by Mali GPUs. The
naming follows[2].
There is no "obvious" linear encoding for a 3-component 10:10:10
packed format, and so DRM_FORMAT_VUY101010 defines a component
order, but not a bit encoding. Again, the naming is meant to be
consistent with DRM_FORMAT_AYUV.
YUV 422 8-bit, 1-plane
----------------------
The existing DRM_FORMAT_YUYV (and the other component orders) are
single-planar YUV 422 8-bit formats. Following the convention of
the component orders of the RGB formats, YUYV has the correct
component order for our AFBC encoding (Y followed by U followed by
V). We can use YUYV for AFBC YUV 422 8-bit.
YUV 422 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 422 10-bit format in drm_fourcc.h
DRM_FORMAT_Y210 is analogous to YUYV, but with 10-bits per sample
packed into the upper 10-bits of 16-bit samples. This format is
supported in both linear and AFBC by Mali GPUs.
YUV 422 10-bit, 2-plane
-----------------------
The recently defined DRM_FORMAT_P010 format is a 10-bit semi-planar
YUV 420 format, which has the correct component ordering for an AFBC
2-plane YUV 420 buffer. The linear layout contains meaningless padding
bits, which will not be encoded in an AFBC stream.
YUV 420 8-bit, 1-plane
----------------------
There is no currently defined single-planar YUV 420, 8-bit format
in drm_fourcc.h. There's differing opinions on whether using the
existing fourcc-implied n_planes where possible is a good idea or
not when using modifiers.
For me, it's much more "obvious" to use NV12 for 2-plane AFBC and
YUV420 for 3-plane AFBC. This keeps the aforementioned separation
between the AFBC codec settings (in the modifier) and the pixel data
format (in the fourcc). With different vendors using AFBC, this helps
to ensure that there is no confusion in interoperation. It also
ensures that the AFBC modifiers describe AFBC itself (which is a
licensable component), and not implementation details which are not
defined by AFBC.
The proposed[1] X0L0 format which Mali-DP supports with Linear layout
is unsuitable, as it contains a 4th 'X' component, and our AFBC
decoder expects only 3 components.
To that end, we propose a new YUV 420 8-bit format. There is no
"obvious" linear encoding for a 3-component 8:8:8, 420, packed format,
and so DRM_FORMAT_YUV420_8BIT defines a component order, but not a
bit encoding. I'm happy to hear different naming suggestions.
YUV 420 8-bit, 2-, 3-plane
--------------------------
These already exist, we can use NV12 and YUV420.
YUV 420 10-bit, 1-plane
-----------------------
As above, no current definition exists, and X0L2 encodes a 4th 'X'
channel.
Analogous to DRM_FORMAT_YUV420_8BIT, we define DRM_FORMAT_YUV420_10BIT.
[1] https://lists.freedesktop.org/archives/dri-devel/2018-July/184598.html
[2] https://docs.microsoft.com/en-us/windows/desktop/medfound/10-bit-and-16-bit-yuv-video-formats
Changes since RFC v1:
- Fix confusing subsampling vs bit-depth X:X:X notation in
descriptions (danvet)
- Rename DRM_FORMAT_AVYU1101010 to DRM_FORMAT_Y410 (Lisa Wu)
- Add drm_format_info structures for the new formats, using the
new 'bpp' field for those with non-integer bytes-per-pixel
- Rebase, including Juha-Pekka Heikkila's format definitions
Changes since RFC v2:
- Rebase on top of latest changes in drm-misc-next
- Change the description of DRM_FORMAT_P210 in __drm_format_info and
drm_fourcc.h so as to make it consistent with other DRM_FORMAT_PXXX
formats.
Changes since v3:
- Added the ack
- Rebased on the latest drm-misc-next
Signed-off-by: Brian Starkey <brian.starkey@arm.com>
Signed-off-by: Ayan Kumar Halder <ayan.halder@arm.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Link: https://patchwork.freedesktop.org/patch/291759/?series=57895&rev=1
2018-10-05 17:27:00 +08:00
|
|
|
{ .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 },
|
2016-10-18 06:41:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
|
|
|
|
if (formats[i].format == format)
|
|
|
|
return &formats[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-10-18 06:41:12 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
2016-10-18 06:41:09 +08:00
|
|
|
EXPORT_SYMBOL(drm_format_info);
|
|
|
|
|
2017-03-22 02:12:16 +08:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
2016-06-09 17:54:08 +08:00
|
|
|
/**
|
|
|
|
* drm_format_num_planes - get the number of planes for format
|
|
|
|
* @format: pixel format (DRM_FORMAT_*)
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The number of planes used by the specified pixel format.
|
|
|
|
*/
|
|
|
|
int drm_format_num_planes(uint32_t format)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
return info ? info->num_planes : 1;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_format_num_planes);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
2016-06-09 17:54:08 +08:00
|
|
|
|
2016-10-18 06:41:10 +08:00
|
|
|
info = drm_format_info(format);
|
|
|
|
if (!info || plane >= info->num_planes)
|
2016-06-09 17:54:08 +08:00
|
|
|
return 0;
|
|
|
|
|
2016-10-18 06:41:10 +08:00
|
|
|
return info->cpp[plane];
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_format_plane_cpp);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
|
|
|
|
* @format: pixel format (DRM_FORMAT_*)
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The horizontal chroma subsampling factor for the
|
|
|
|
* specified pixel format.
|
|
|
|
*/
|
|
|
|
int drm_format_horz_chroma_subsampling(uint32_t format)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
return info ? info->hsub : 1;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
|
|
|
|
* @format: pixel format (DRM_FORMAT_*)
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The vertical chroma subsampling factor for the
|
|
|
|
* specified pixel format.
|
|
|
|
*/
|
|
|
|
int drm_format_vert_chroma_subsampling(uint32_t format)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
return info ? info->vsub : 1;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
if (!info || plane >= info->num_planes)
|
2016-06-09 17:54:08 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (plane == 0)
|
|
|
|
return width;
|
|
|
|
|
2016-10-18 06:41:10 +08:00
|
|
|
return width / info->hsub;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2016-10-18 06:41:10 +08:00
|
|
|
const struct drm_format_info *info;
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
if (!info || plane >= info->num_planes)
|
2016-06-09 17:54:08 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (plane == 0)
|
|
|
|
return height;
|
|
|
|
|
2016-10-18 06:41:10 +08:00
|
|
|
return height / info->vsub;
|
2016-06-09 17:54:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(drm_format_plane_height);
|
drm/fourcc: Add char_per_block, block_w and block_h in drm_format_info
For some pixel formats .cpp structure in drm_format info it's not
enough to describe the peculiarities of the pixel layout, for example
tiled formats or packed formats at bit level.
What's implemented here is to add three new members to drm_format_info
that could describe such formats:
- char_per_block[3]
- block_w[3]
- block_h[3]
char_per_block will be put in a union alongside cpp, for transparent
compatibility with the existing format descriptions.
Regarding, block_w and block_h they are intended to be used through
their equivalent getters drm_format_info_block_width /
drm_format_info_block_height, the reason of the getters is to abstract
the fact that for normal formats block_w and block_h will be unset/0,
but the methods will be returning 1.
Additionally, convenience function drm_format_info_min_pitch had been
added that computes the minimum required pitch for a given pixel
format and buffer width.
Using that the following drm core functions had been updated to
generically handle both block and non-block formats:
- drm_fb_cma_get_gem_addr: for block formats it will just return the
beginning of the block.
- framebuffer_check: Use the newly added drm_format_info_min_pitch.
- drm_gem_fb_create_with_funcs: Use the newly added
drm_format_info_min_pitch.
- In places where is not expecting to handle block formats, like fbdev
helpers I just added some warnings in case the block width/height
are greater than 1.
Changes since v3:
- Add helper function for computing the minimum required pitch.
- Improve/cleanup documentation
Changes since v8:
- Fixed build on 32bits arm architectures, with:
- return DIV_ROUND_UP((u64)buffer_width * info->char_per_block[plane],
+ return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
Reviewed-by: Brian Starkey <brian.starkey@arm.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181101170055.5433-1-alexandru-cosmin.gheorghe@arm.com
2018-11-02 01:02:05 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|