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 },
|
|
|
|
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .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);
|