2019-04-17 07:57:24

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

DRM comes with an extensive format support to retrieve the various
parameters associated with a given format (such as the subsampling, or the
bits per pixel), as well as some helpers and utilities to ease the driver
development.

v4l2, on the other side, doesn't provide such facilities, leaving each
driver reimplement a subset of the formats parameters for the one supported
by that particular driver. This leads to a lot of duplication and
boilerplate code in the v4l2 drivers.

This series tries to address this by moving the DRM format API into lib and
turning it into a more generic API. In order to do this, we've needed to do
some preliminary changes on the DRM drivers, then moved the API and finally
converted a v4l2 driver to give an example of how such library could be
used.

Let me know what you think,
Maxime

Changes from RFC:
- Rebased on next
- Fixed the various formats mapping
- Added tags
- Did most of the formats functions as inline functions
- Used a consistent prefix for all the utilities functions
- Fixed the compilation breakages, and did a run of allmodconfig for arm,
arm64 and x86_64
- Fixed out of array bounds warnings in the image_format_info_block_*
functions
- Added License and copyright headers on missing files

Maxime Ripard (20):
drm: Remove users of drm_format_num_planes
drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
drm: Replace instances of drm_format_info by drm_get_format_info
lib: Add video format information library
drm/fb: Move from drm_format_info to image_format_info
drm/malidp: Convert to generic image format library
drm/client: Convert to generic image format library
drm/exynos: Convert to generic image format library
drm/i915: Convert to generic image format library
drm/ipuv3: Convert to generic image format library
drm/msm: Convert to generic image format library
drm/omap: Convert to generic image format library
drm/rockchip: Convert to generic image format library
drm/tegra: Convert to generic image format library
drm/fourcc: Remove old DRM format API
lib: image-formats: Add v4l2 formats support
lib: image-formats: Add more functions
media: sun6i: Convert to the image format API

drivers/gpu/drm/Kconfig | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +-
drivers/gpu/drm/arm/malidp_drv.c | 3 +-
drivers/gpu/drm/arm/malidp_hw.c | 3 +-
drivers/gpu/drm/arm/malidp_mw.c | 2 +-
drivers/gpu/drm/arm/malidp_planes.c | 20 +-
drivers/gpu/drm/armada/armada_fb.c | 3 +-
drivers/gpu/drm/armada/armada_overlay.c | 2 +-
drivers/gpu/drm/armada/armada_plane.c | 2 +-
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 11 +-
drivers/gpu/drm/bochs/bochs.h | 4 +-
drivers/gpu/drm/bochs/bochs_hw.c | 2 +-
drivers/gpu/drm/drm_client.c | 7 +-
drivers/gpu/drm/drm_fb_cma_helper.c | 4 +-
drivers/gpu/drm/drm_fb_helper.c | 14 +-
drivers/gpu/drm/drm_format_helper.c | 4 +-
drivers/gpu/drm/drm_fourcc.c | 345 +-----
drivers/gpu/drm/drm_framebuffer.c | 10 +-
drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 +-
drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_ipp.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_ipp.h | 4 +-
drivers/gpu/drm/exynos/exynos_drm_scaler.c | 3 +-
drivers/gpu/drm/gma500/framebuffer.c | 4 +-
drivers/gpu/drm/i915/i915_drv.h | 6 +-
drivers/gpu/drm/i915/intel_display.c | 14 +-
drivers/gpu/drm/i915/intel_pm.c | 6 +-
drivers/gpu/drm/i915/intel_sprite.c | 3 +-
drivers/gpu/drm/imx/ipuv3-plane.c | 19 +-
drivers/gpu/drm/mediatek/mtk_drm_fb.c | 8 +-
drivers/gpu/drm/meson/meson_overlay.c | 14 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 11 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 25 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 8 +-
drivers/gpu/drm/msm/msm_fb.c | 18 +-
drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +-
drivers/gpu/drm/omapdrm/omap_fb.c | 15 +-
drivers/gpu/drm/radeon/radeon_fb.c | 4 +-
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 17 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 +-
drivers/gpu/drm/selftests/Makefile | 3 +-
drivers/gpu/drm/selftests/drm_modeset_selftests.h | 3 +-
drivers/gpu/drm/selftests/test-drm_format.c | 280 +----
drivers/gpu/drm/selftests/test-drm_modeset_common.h | 3 +-
drivers/gpu/drm/stm/ltdc.c | 2 +-
drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +-
drivers/gpu/drm/sun4i/sun4i_frontend.c | 18 +-
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +-
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 +-
drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 5 +-
drivers/gpu/drm/tegra/fb.c | 14 +-
drivers/gpu/drm/tegra/plane.c | 4 +-
drivers/gpu/drm/vc4/vc4_plane.c | 15 +-
drivers/gpu/drm/zte/zx_plane.c | 6 +-
drivers/gpu/ipu-v3/ipu-pre.c | 3 +-
drivers/gpu/ipu-v3/ipu-prg.c | 3 +-
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 89 +-
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 49 +-
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 6 +-
drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c | 11 +-
include/drm/drm_fourcc.h | 219 +---
include/drm/drm_framebuffer.h | 4 +-
include/drm/drm_mode_config.h | 5 +-
include/linux/image-formats.h | 438 ++++++-
lib/Kconfig | 7 +-
lib/Makefile | 3 +-
lib/image-formats-selftests.c | 325 +++++-
lib/image-formats.c | 717 ++++++++++-
70 files changed, 1740 insertions(+), 1174 deletions(-)
delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
create mode 100644 include/linux/image-formats.h
create mode 100644 lib/image-formats-selftests.c
create mode 100644 lib/image-formats.c

base-commit: de3c659c83ce88d495f2a36397071fdd0a337345
--
git-series 0.9.1


2019-04-17 07:56:12

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 01/20] drm: Remove users of drm_format_num_planes

drm_format_num_planes() is basically a lookup in the drm_format_info table
plus an access to the num_planes field 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 drm_format_num_planes 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.

Reviewed-by: Emil Velikov <[email protected]>
Reviewed-by: Paul Kocialkowski <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/arm/malidp_mw.c | 2 +-
drivers/gpu/drm/armada/armada_fb.c | 3 ++-
drivers/gpu/drm/drm_fourcc.c | 16 ----------------
drivers/gpu/drm/mediatek/mtk_drm_fb.c | 6 ++++--
drivers/gpu/drm/meson/meson_overlay.c | 2 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 9 ++++++---
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 3 ++-
drivers/gpu/drm/msm/msm_fb.c | 8 ++++++--
drivers/gpu/drm/omapdrm/omap_fb.c | 4 +++-
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 6 +++---
drivers/gpu/drm/tegra/fb.c | 3 ++-
drivers/gpu/drm/vc4/vc4_plane.c | 2 +-
drivers/gpu/drm/zte/zx_plane.c | 4 +---
include/drm/drm_fourcc.h | 1 -
14 files changed, 32 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index 5f102bdaf841..2e812525025d 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -158,7 +158,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
return -EINVAL;
}

- n_planes = drm_format_num_planes(fb->format->format);
+ n_planes = fb->format->num_planes;
for (i = 0; i < n_planes; i++) {
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);
/* memory write buffers are never rotated */
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index 058ac7d9920f..a2f6472eb482 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -87,6 +87,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
{
+ const struct drm_format_info *info = drm_get_format_info(dev, mode);
struct armada_gem_object *obj;
struct armada_framebuffer *dfb;
int ret;
@@ -97,7 +98,7 @@ struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
mode->pitches[2]);

/* We can only handle a single plane at the moment */
- if (drm_format_num_planes(mode->pixel_format) > 1 &&
+ if (info->num_planes > 1 &&
(mode->handles[0] != mode->handles[1] ||
mode->handles[0] != mode->handles[2])) {
ret = -EINVAL;
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 6ea55fb4526d..873c0001d8c8 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -333,22 +333,6 @@ drm_get_format_info(struct drm_device *dev,
EXPORT_SYMBOL(drm_get_format_info);

/**
- * 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)
-{
- const struct drm_format_info *info;
-
- info = drm_format_info(format);
- return info ? info->num_planes : 1;
-}
-EXPORT_SYMBOL(drm_format_num_planes);
-
-/**
* drm_format_plane_cpp - determine the bytes per pixel value
* @format: pixel format (DRM_FORMAT_*)
* @plane: plane index
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
index e20fcaef2851..68fdef8b12bd 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
@@ -32,10 +32,11 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode,
struct drm_gem_object *obj)
{
+ const struct drm_format_info *info = drm_get_format_info(dev, mode);
struct drm_framebuffer *fb;
int ret;

- if (drm_format_num_planes(mode->pixel_format) != 1)
+ if (info->num_planes != 1)
return ERR_PTR(-EINVAL);

fb = kzalloc(sizeof(*fb), GFP_KERNEL);
@@ -88,6 +89,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *cmd)
{
+ const struct drm_format_info *info = drm_get_format_info(dev, cmd);
struct drm_framebuffer *fb;
struct drm_gem_object *gem;
unsigned int width = cmd->width;
@@ -95,7 +97,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
unsigned int size, bpp;
int ret;

- if (drm_format_num_planes(cmd->pixel_format) != 1)
+ if (info->num_planes != 1)
return ERR_PTR(-EINVAL);

gem = drm_gem_object_lookup(file, cmd->handles[0]);
diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index bdbf925ff3e8..fb8515b2860c 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -458,7 +458,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
}

/* Update Canvas with buffer address */
- priv->viu.vd1_planes = drm_format_num_planes(fb->format->format);
+ priv->viu.vd1_planes = fb->format->num_planes;

switch (priv->viu.vd1_planes) {
case 3:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index f59fe1a9f4b9..c3d491e8d44b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -1040,10 +1040,11 @@ int dpu_format_check_modified_format(
const struct drm_mode_fb_cmd2 *cmd,
struct drm_gem_object **bos)
{
- int ret, i, num_base_fmt_planes;
+ const struct drm_format_info *info;
const struct dpu_format *fmt;
struct dpu_hw_fmt_layout layout;
uint32_t bos_total_size = 0;
+ int ret, i;

if (!msm_fmt || !cmd || !bos) {
DRM_ERROR("invalid arguments\n");
@@ -1051,14 +1052,16 @@ int dpu_format_check_modified_format(
}

fmt = to_dpu_format(msm_fmt);
- num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
+ info = drm_format_info(fmt->base.pixel_format);
+ if (!info)
+ return -EINVAL;

ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
&layout, cmd->pitches);
if (ret)
return ret;

- for (i = 0; i < num_base_fmt_planes; i++) {
+ for (i = 0; i < info->num_planes; i++) {
if (!bos[i]) {
DRM_ERROR("invalid handle for plane %d\n", i);
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index 6153514db04c..72ab8d89efa4 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -127,13 +127,14 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
const struct mdp_format *format,
u32 width, bool hdecim)
{
+ const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(smp);
int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
int i, hsub, nplanes, nlines;
u32 fmt = format->base.pixel_format;
uint32_t blkcfg = 0;

- nplanes = drm_format_num_planes(fmt);
+ nplanes = info->num_planes;
hsub = drm_format_horz_chroma_subsampling(fmt);

/* different if BWC (compressed framebuffer?) enabled: */
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 136058978e0f..432beddafb9e 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -106,9 +106,11 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb)
struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
+ const struct drm_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct drm_gem_object *bos[4] = {0};
struct drm_framebuffer *fb;
- int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
+ int ret, i, n = info->num_planes;

for (i = 0; i < n; i++) {
bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
@@ -135,6 +137,8 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
+ const struct drm_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_framebuffer *msm_fb = NULL;
@@ -147,7 +151,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
dev, mode_cmd, mode_cmd->width, mode_cmd->height,
(char *)&mode_cmd->pixel_format);

- n = drm_format_num_planes(mode_cmd->pixel_format);
+ n = info->num_planes;
hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 4f8eb9d08f99..cfb641363a32 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -298,7 +298,9 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
- unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format);
+ const struct drm_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
+ unsigned int num_planes = info->num_planes;
struct drm_gem_object *bos[4];
struct drm_framebuffer *fb;
int i;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 97438bbbe389..606d176d5d96 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -74,19 +74,19 @@ static struct drm_framebuffer *
rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
+ const struct drm_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct drm_framebuffer *fb;
struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
struct drm_gem_object *obj;
unsigned int hsub;
unsigned int vsub;
- int num_planes;
+ int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER);
int ret;
int i;

hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
- num_planes = min(drm_format_num_planes(mode_cmd->pixel_format),
- ROCKCHIP_MAX_FB_BUFFER);

for (i = 0; i < num_planes; i++) {
unsigned int width = mode_cmd->width / (i ? hsub : 1);
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 1dd83a757dba..da0747e317b7 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -131,6 +131,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *cmd)
{
+ const struct drm_format_info *info = drm_get_format_info(drm, cmd);
unsigned int hsub, vsub, i;
struct tegra_bo *planes[4];
struct drm_gem_object *gem;
@@ -140,7 +141,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);

- for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
+ for (i = 0; i < info->num_planes; i++) {
unsigned int width = cmd->width / (i ? hsub : 1);
unsigned int height = cmd->height / (i ? vsub : 1);
unsigned int size, bpp;
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 4d918d3e4858..e3c0a350cb77 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -592,7 +592,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
u32 ctl0_offset = vc4_state->dlist_count;
const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
- int num_planes = drm_format_num_planes(format->drm);
+ int num_planes = fb->format->num_planes;
u32 h_subsample, v_subsample;
bool mix_plane_alpha;
bool covers_screen;
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index 83d236fd893c..c6a8be444300 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -199,7 +199,6 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane,
u32 dst_x, dst_y, dst_w, dst_h;
uint32_t format;
int fmt;
- int num_planes;
int i;

if (!fb)
@@ -218,9 +217,8 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane,
dst_h = drm_rect_height(dst);

/* Set up data address registers for Y, Cb and Cr planes */
- num_planes = drm_format_num_planes(format);
paddr_reg = layer + VL_Y;
- for (i = 0; i < num_planes; i++) {
+ for (i = 0; i < fb->format->num_planes; i++) {
cma_obj = drm_fb_cma_get_gem_obj(fb, i);
paddr = cma_obj->paddr + fb->offsets[i];
paddr += src_y * fb->pitches[i];
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index b3d9d88ab290..41779b327d91 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -268,7 +268,6 @@ drm_get_format_info(struct drm_device *dev,
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
uint32_t bpp, uint32_t depth);
-int drm_format_num_planes(uint32_t format);
int drm_format_plane_cpp(uint32_t format, int plane);
int drm_format_horz_chroma_subsampling(uint32_t format);
int drm_format_vert_chroma_subsampling(uint32_t format);
--
git-series 0.9.1

2019-04-17 07:56:25

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 05/20] drm: Replace instances of drm_format_info by drm_get_format_info

drm_get_format_info directly calls into drm_format_info, but takes directly
a struct drm_mode_fb_cmd2 pointer, instead of the fourcc directly. It's
shorter to not dereference it, and we can customise the behaviour at the
driver level if we want to, so let's switch to it where it makes sense.

Reviewed-by: Emil Velikov <[email protected]>
Reviewed-by: Paul Kocialkowski <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 ++--
drivers/gpu/drm/gma500/framebuffer.c | 2 +-
drivers/gpu/drm/omapdrm/omap_fb.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 06e73a343724..6edae6458be8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -121,8 +121,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
- const struct drm_format_info *info = drm_get_format_info(dev,
- mode_cmd);
+ const struct drm_format_info *info;
struct amdgpu_device *adev = rfbdev->adev;
struct drm_gem_object *gobj = NULL;
struct amdgpu_bo *abo = NULL;
@@ -133,6 +132,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
int height = mode_cmd->height;
u32 cpp;

+ info = drm_get_format_info(adev->ddev, mode_cmd);
cpp = drm_format_info_plane_cpp(info, 0);

/* need to align pitch with crtc limits */
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index a9d3a4a30ab8..1794ab90b2cc 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -232,7 +232,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
* Reject unknown formats, YUV formats, and formats with more than
* 4 bytes per pixel.
*/
- info = drm_format_info(mode_cmd->pixel_format);
+ info = drm_get_format_info(dev, mode_cmd);
if (!info || !info->depth || info->cpp[0] > 4)
return -EINVAL;

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index cfb641363a32..6557b2d6e16e 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -339,7 +339,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
dev, mode_cmd, mode_cmd->width, mode_cmd->height,
(char *)&mode_cmd->pixel_format);

- format = drm_format_info(mode_cmd->pixel_format);
+ format = drm_get_format_info(dev, mode_cmd);

for (i = 0; i < ARRAY_SIZE(formats); i++) {
if (formats[i] == mode_cmd->pixel_format)
--
git-series 0.9.1

2019-04-17 07:56:37

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 17/20] drm/fourcc: Remove old DRM format API

Now that all the clients of the old drm_format* API have been converted to
the generic one, let's remove it.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/Kconfig | 1 +-
drivers/gpu/drm/drm_fourcc.c | 219 +----------
drivers/gpu/drm/selftests/Makefile | 3 +-
drivers/gpu/drm/selftests/drm_modeset_selftests.h | 3 +-
drivers/gpu/drm/selftests/test-drm_format.c | 280 +-------------
drivers/gpu/drm/selftests/test-drm_modeset_common.h | 3 +-
include/drm/drm_fourcc.h | 272 +-------------
7 files changed, 2 insertions(+), 779 deletions(-)
delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index a5bef1c83e7f..d7e215e50d9f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -54,6 +54,7 @@ config DRM_DEBUG_SELFTEST
tristate "kselftests for DRM"
depends on DRM
depends on DEBUG_KERNEL
+ select IMAGE_FORMATS_SELFTESTS
select PRIME_NUMBERS
select DRM_LIB_RANDOM
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 6537f4906c50..4f262e1a202a 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -150,163 +150,6 @@ const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf
}
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
@@ -331,65 +174,3 @@ drm_get_format_info(struct drm_device *dev,
return info;
}
EXPORT_SYMBOL(drm_get_format_info);
-
-/**
- * drm_format_info_block_width - width in pixels of block.
- * @info: pixel format info
- * @plane: plane index
- *
- * Returns:
- * The width in pixels of a block, depending on the plane index.
- */
-unsigned int drm_format_info_block_width(const struct drm_format_info *info,
- int plane)
-{
- if (!info || plane < 0 || plane >= info->num_planes)
- return 0;
-
- if (!info->block_w[plane])
- return 1;
- return info->block_w[plane];
-}
-EXPORT_SYMBOL(drm_format_info_block_width);
-
-/**
- * drm_format_info_block_height - height in pixels of a block
- * @info: pixel format info
- * @plane: plane index
- *
- * Returns:
- * The height in pixels of a block, depending on the plane index.
- */
-unsigned int drm_format_info_block_height(const struct drm_format_info *info,
- int plane)
-{
- if (!info || plane < 0 || plane >= info->num_planes)
- return 0;
-
- if (!info->block_h[plane])
- return 1;
- return info->block_h[plane];
-}
-EXPORT_SYMBOL(drm_format_info_block_height);
-
-/**
- * drm_format_info_min_pitch - computes the minimum required pitch in bytes
- * @info: pixel format info
- * @plane: plane index
- * @buffer_width: buffer width in pixels
- *
- * Returns:
- * The minimum required pitch in bytes for a buffer by taking into consideration
- * the pixel format information and the buffer width.
- */
-uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
- int plane, unsigned int buffer_width)
-{
- if (!info || plane < 0 || plane >= info->num_planes)
- return 0;
-
- return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
- drm_format_info_block_width(info, plane) *
- drm_format_info_block_height(info, plane));
-}
-EXPORT_SYMBOL(drm_format_info_min_pitch);
diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
index 1bb73dc4c88c..e32921691662 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,5 +1,4 @@
test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
- test-drm_format.o test-drm_framebuffer.o \
- test-drm_damage_helper.o
+ test-drm_framebuffer.o test-drm_damage_helper.o

obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index 464753746013..4a2ef84c2762 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -7,9 +7,6 @@
* Tests are executed in order by igt/drm_selftests_helper
*/
selftest(check_plane_state, igt_check_plane_state)
-selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
-selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
-selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch)
selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
selftest(damage_iter_no_damage, igt_damage_iter_no_damage)
selftest(damage_iter_no_damage_fractional_src, igt_damage_iter_no_damage_fractional_src)
diff --git a/drivers/gpu/drm/selftests/test-drm_format.c b/drivers/gpu/drm/selftests/test-drm_format.c
deleted file mode 100644
index c5e212afa27a..000000000000
--- a/drivers/gpu/drm/selftests/test-drm_format.c
+++ /dev/null
@@ -1,280 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_format functions
- */
-
-#define pr_fmt(fmt) "drm_format: " fmt
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#include <drm/drm_fourcc.h>
-
-#include "test-drm_modeset_common.h"
-
-int igt_check_drm_format_block_width(void *ignored)
-{
- const struct drm_format_info *info = NULL;
-
- /* Test invalid arguments */
- FAIL_ON(drm_format_info_block_width(info, 0) != 0);
- FAIL_ON(drm_format_info_block_width(info, -1) != 0);
- FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-
- /* Test 1 plane format */
- info = drm_format_info(DRM_FORMAT_XRGB4444);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_width(info, 0) != 1);
- FAIL_ON(drm_format_info_block_width(info, 1) != 0);
- FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
- /* Test 2 planes format */
- info = drm_format_info(DRM_FORMAT_NV12);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_width(info, 0) != 1);
- FAIL_ON(drm_format_info_block_width(info, 1) != 1);
- FAIL_ON(drm_format_info_block_width(info, 2) != 0);
- FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
- /* Test 3 planes format */
- info = drm_format_info(DRM_FORMAT_YUV422);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_width(info, 0) != 1);
- FAIL_ON(drm_format_info_block_width(info, 1) != 1);
- FAIL_ON(drm_format_info_block_width(info, 2) != 1);
- FAIL_ON(drm_format_info_block_width(info, 3) != 0);
- FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
- /* Test a tiled format */
- info = drm_format_info(DRM_FORMAT_X0L0);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_width(info, 0) != 2);
- FAIL_ON(drm_format_info_block_width(info, 1) != 0);
- FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
- return 0;
-}
-
-int igt_check_drm_format_block_height(void *ignored)
-{
- const struct drm_format_info *info = NULL;
-
- /* Test invalid arguments */
- FAIL_ON(drm_format_info_block_height(info, 0) != 0);
- FAIL_ON(drm_format_info_block_height(info, -1) != 0);
- FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-
- /* Test 1 plane format */
- info = drm_format_info(DRM_FORMAT_XRGB4444);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_height(info, 0) != 1);
- FAIL_ON(drm_format_info_block_height(info, 1) != 0);
- FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
- /* Test 2 planes format */
- info = drm_format_info(DRM_FORMAT_NV12);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_height(info, 0) != 1);
- FAIL_ON(drm_format_info_block_height(info, 1) != 1);
- FAIL_ON(drm_format_info_block_height(info, 2) != 0);
- FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
- /* Test 3 planes format */
- info = drm_format_info(DRM_FORMAT_YUV422);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_height(info, 0) != 1);
- FAIL_ON(drm_format_info_block_height(info, 1) != 1);
- FAIL_ON(drm_format_info_block_height(info, 2) != 1);
- FAIL_ON(drm_format_info_block_height(info, 3) != 0);
- FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
- /* Test a tiled format */
- info = drm_format_info(DRM_FORMAT_X0L0);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_block_height(info, 0) != 2);
- FAIL_ON(drm_format_info_block_height(info, 1) != 0);
- FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
- return 0;
-}
-
-int igt_check_drm_format_min_pitch(void *ignored)
-{
- const struct drm_format_info *info = NULL;
-
- /* Test invalid arguments */
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- /* Test 1 plane 8 bits per pixel format */
- info = drm_format_info(DRM_FORMAT_RGB332);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX);
- FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
- (uint64_t)(UINT_MAX - 1));
-
- /* Test 1 plane 16 bits per pixel format */
- info = drm_format_info(DRM_FORMAT_XRGB4444);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX * 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
- (uint64_t)(UINT_MAX - 1) * 2);
-
- /* Test 1 plane 24 bits per pixel format */
- info = drm_format_info(DRM_FORMAT_RGB888);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 3);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 6);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1920);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 3072);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 5760);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 12288);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2013);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX * 3);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
- (uint64_t)(UINT_MAX - 1) * 3);
-
- /* Test 1 plane 32 bits per pixel format */
- info = drm_format_info(DRM_FORMAT_ABGR8888);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 4);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 8);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 2560);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 4096);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 7680);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 16384);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2684);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX * 4);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
- (uint64_t)(UINT_MAX - 1) * 4);
-
- /* Test 2 planes format */
- info = drm_format_info(DRM_FORMAT_NV12);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 640);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 1024);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 1920);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 4096);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 672);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX);
- FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
- (uint64_t)UINT_MAX + 1);
- FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
- (uint64_t)(UINT_MAX - 1));
- FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
- (uint64_t)(UINT_MAX - 1));
-
- /* Test 3 planes 8 bits per pixel format */
- info = drm_format_info(DRM_FORMAT_YUV422);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 3, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 1);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 1) != 1);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 2) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 2) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 320);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 320) != 320);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 512);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 512) != 512);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 960);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 960) != 960);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 2048);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 2048) != 2048);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 336);
- FAIL_ON(drm_format_info_min_pitch(info, 2, 336) != 336);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX);
- FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
- (uint64_t)UINT_MAX / 2 + 1);
- FAIL_ON(drm_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
- (uint64_t)UINT_MAX / 2 + 1);
- FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
- (uint64_t)(UINT_MAX - 1) / 2);
- FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
- (uint64_t)(UINT_MAX - 1) / 2);
- FAIL_ON(drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
- (uint64_t)(UINT_MAX - 1) / 2);
-
- /* Test tiled format */
- info = drm_format_info(DRM_FORMAT_X0L2);
- FAIL_ON(!info);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
- FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192);
- FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
- (uint64_t)UINT_MAX * 2);
- FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
- (uint64_t)(UINT_MAX - 1) * 2);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
index 8c76f09c12d1..fb2b8fbd7566 100644
--- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h
+++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
@@ -14,9 +14,6 @@
#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")

int igt_check_plane_state(void *ignored);
-int igt_check_drm_format_block_width(void *ignored);
-int igt_check_drm_format_block_height(void *ignored);
-int igt_check_drm_format_min_pitch(void *ignored);
int igt_check_drm_framebuffer_create(void *ignored);
int igt_damage_iter_no_damage(void *ignored);
int igt_damage_iter_no_damage_fractional_src(void *ignored);
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 38f152b5da08..8ca45b2be9ca 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -52,91 +52,6 @@ struct drm_mode_fb_cmd2;
struct image_format_info;

/**
- * struct drm_format_info - information about a DRM format
- */
-struct drm_format_info {
- /** @format: 4CC format identifier (DRM_FORMAT_*) */
- u32 format;
-
- /**
- * @depth:
- *
- * Color depth (number of bits per pixel excluding padding bits),
- * valid for a subset of RGB formats only. This is a legacy field, do
- * not use in new code and set to 0 for new formats.
- */
- u8 depth;
-
- /** @num_planes: Number of color planes (1 to 3) */
- u8 num_planes;
-
- union {
- /**
- * @cpp:
- *
- * Number of bytes per pixel (per plane), this is aliased with
- * @char_per_block. It is deprecated in favour of using the
- * triplet @char_per_block, @block_w, @block_h for better
- * describing the pixel format.
- */
- u8 cpp[3];
-
- /**
- * @char_per_block:
- *
- * Number of bytes per block (per plane), where blocks are
- * defined as a rectangle of pixels which are stored next to
- * each other in a byte aligned memory region. Together with
- * @block_w and @block_h this is used to properly describe tiles
- * in tiled formats or to describe groups of pixels in packed
- * formats for which the memory needed for a single pixel is not
- * byte aligned.
- *
- * @cpp has been kept for historical reasons because there are
- * a lot of places in drivers where it's used. In drm core for
- * generic code paths the preferred way is to use
- * @char_per_block, drm_format_info_block_width() and
- * drm_format_info_block_height() which allows handling both
- * block and non-block formats in the same way.
- *
- * For formats that are intended to be used only with non-linear
- * modifiers both @cpp and @char_per_block must be 0 in the
- * generic format table. Drivers could supply accurate
- * information from their drm_mode_config.get_format_info hook
- * if they want the core to be validating the pitch.
- */
- u8 char_per_block[3];
- };
-
- /**
- * @block_w:
- *
- * Block width in pixels, this is intended to be accessed through
- * drm_format_info_block_width()
- */
- u8 block_w[3];
-
- /**
- * @block_h:
- *
- * Block height in pixels, this is intended to be accessed through
- * drm_format_info_block_height()
- */
- u8 block_h[3];
-
- /** @hsub: Horizontal chroma subsampling factor */
- u8 hsub;
- /** @vsub: Vertical chroma subsampling factor */
- u8 vsub;
-
- /** @has_alpha: Does the format embeds an alpha component? */
- bool has_alpha;
-
- /** @is_yuv: Is it a YUV format? */
- bool is_yuv;
-};
-
-/**
* struct drm_format_name_buf - name of a DRM format
* @str: string buffer containing the format name
*/
@@ -144,199 +59,12 @@ struct drm_format_name_buf {
char str[32];
};

-/**
- * drm_format_info_is_yuv_packed - check that the format info matches a YUV
- * format with data laid in a single plane
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a packed YUV format.
- */
-static inline bool
-drm_format_info_is_yuv_packed(const struct drm_format_info *info)
-{
- return info->is_yuv && info->num_planes == 1;
-}
-
-/**
- * drm_format_info_is_yuv_semiplanar - check that the format info matches a YUV
- * format with data laid in two planes (luminance and chrominance)
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a semiplanar YUV format.
- */
-static inline bool
-drm_format_info_is_yuv_semiplanar(const struct drm_format_info *info)
-{
- return info->is_yuv && info->num_planes == 2;
-}
-
-/**
- * drm_format_info_is_yuv_planar - check that the format info matches a YUV
- * format with data laid in three planes (one for each YUV component)
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a planar YUV format.
- */
-static inline bool
-drm_format_info_is_yuv_planar(const struct drm_format_info *info)
-{
- return info->is_yuv && info->num_planes == 3;
-}
-
-/**
- * drm_format_info_is_yuv_sampling_410 - check that the format info matches a
- * YUV format with 4:1:0 sub-sampling
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a YUV format with 4:1:0
- * sub-sampling.
- */
-static inline bool
-drm_format_info_is_yuv_sampling_410(const struct drm_format_info *info)
-{
- return info->is_yuv && info->hsub == 4 && info->vsub == 4;
-}
-
-/**
- * drm_format_info_is_yuv_sampling_411 - check that the format info matches a
- * YUV format with 4:1:1 sub-sampling
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a YUV format with 4:1:1
- * sub-sampling.
- */
-static inline bool
-drm_format_info_is_yuv_sampling_411(const struct drm_format_info *info)
-{
- return info->is_yuv && info->hsub == 4 && info->vsub == 1;
-}
-
-/**
- * drm_format_info_is_yuv_sampling_420 - check that the format info matches a
- * YUV format with 4:2:0 sub-sampling
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a YUV format with 4:2:0
- * sub-sampling.
- */
-static inline bool
-drm_format_info_is_yuv_sampling_420(const struct drm_format_info *info)
-{
- return info->is_yuv && info->hsub == 2 && info->vsub == 2;
-}
-
-/**
- * drm_format_info_is_yuv_sampling_422 - check that the format info matches a
- * YUV format with 4:2:2 sub-sampling
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a YUV format with 4:2:2
- * sub-sampling.
- */
-static inline bool
-drm_format_info_is_yuv_sampling_422(const struct drm_format_info *info)
-{
- return info->is_yuv && info->hsub == 2 && info->vsub == 1;
-}
-
-/**
- * drm_format_info_is_yuv_sampling_444 - check that the format info matches a
- * YUV format with 4:4:4 sub-sampling
- * @info: format info
- *
- * Returns:
- * A boolean indicating whether the format info matches a YUV format with 4:4:4
- * sub-sampling.
- */
-static inline bool
-drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info)
-{
- return info->is_yuv && info->hsub == 1 && info->vsub == 1;
-}
-
-/**
- * drm_format_info_plane_cpp - determine the bytes per pixel value
- * @format: pixel format info
- * @plane: plane index
- *
- * Returns:
- * The bytes per pixel value for the specified plane.
- */
-static inline
-int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane)
-{
- if (!info || plane >= info->num_planes)
- return 0;
-
- return info->cpp[plane];
-}
-
-/**
- * drm_format_info_plane_width - width of the plane given the first plane
- * @format: pixel format info
- * @width: width of the first plane
- * @plane: plane index
- *
- * Returns:
- * The width of @plane, given that the width of the first plane is @width.
- */
-static inline
-int drm_format_info_plane_width(const struct drm_format_info *info, int width,
- int plane)
-{
- if (!info || plane >= info->num_planes)
- return 0;
-
- if (plane == 0)
- return width;
-
- return width / info->hsub;
-}
-
-/**
- * drm_format_info_plane_height - height of the plane given the first plane
- * @format: pixel format info
- * @height: height of the first plane
- * @plane: plane index
- *
- * Returns:
- * The height of @plane, given that the height of the first plane is @height.
- */
-static inline
-int drm_format_info_plane_height(const struct drm_format_info *info, int height,
- int plane)
-{
- if (!info || plane >= info->num_planes)
- return 0;
-
- if (plane == 0)
- return height;
-
- return height / info->vsub;
-}
-
-const struct drm_format_info *__drm_format_info(u32 format);
-const struct drm_format_info *drm_format_info(u32 format);
-
const struct image_format_info *
drm_get_format_info(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd);
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
uint32_t bpp, uint32_t depth);
-unsigned int drm_format_info_block_width(const struct drm_format_info *info,
- int plane);
-unsigned int drm_format_info_block_height(const struct drm_format_info *info,
- int plane);
-uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
- int plane, unsigned int buffer_width);
const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf);

#endif /* __DRM_FOURCC_H__ */
--
git-series 0.9.1

2019-04-17 07:56:43

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 19/20] lib: image-formats: Add more functions

V4L2 drivers typically need a few more helpers compared to DRM drivers, so
let's add them.

Signed-off-by: Maxime Ripard <[email protected]>
---
include/linux/image-formats.h | 42 ++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+)

diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
index b78b8e861fc9..a2cf3528bd31 100644
--- a/include/linux/image-formats.h
+++ b/include/linux/image-formats.h
@@ -388,6 +388,48 @@ uint64_t image_format_info_min_pitch(const struct image_format_info *info,
image_format_info_block_height(info, plane));
}

+/**
+ * image_format_info_plane_stride - determine the stride value
+ * @format: pointer to the image_format_info
+ * @width: plane width
+ * @plane: plane index
+ *
+ * Returns:
+ * The bytes per pixel value for the specified plane.
+ */
+static inline
+unsigned int image_format_info_plane_stride(const struct image_format_info *format,
+ unsigned int width, int plane)
+{
+ if (!format || plane >= format->num_planes)
+ return 0;
+
+ return image_format_info_plane_width(format, width, plane) *
+ image_format_info_plane_cpp(format, plane);
+}
+
+/**
+ * image_format_info_plane_size - determine the size value
+ * @format: pointer to the image_format_info
+ * @width: plane width
+ * @height: plane width
+ * @plane: plane index
+ *
+ * Returns:
+ * The size of the plane buffer.
+ */
+static inline
+unsigned int image_format_info_plane_size(const struct image_format_info *format,
+ unsigned int width, unsigned int height,
+ int plane)
+{
+ if (!format || plane >= format->num_planes)
+ return 0;
+
+ return image_format_info_plane_stride(format, width, plane) *
+ image_format_info_plane_height(format, height, plane);
+}
+
const struct image_format_info *__image_format_drm_lookup(u32 drm);
const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2);
const struct image_format_info *image_format_drm_lookup(u32 drm);
--
git-series 0.9.1

2019-04-17 07:56:47

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 20/20] media: sun6i: Convert to the image format API

The image format API allows us to remove some of the computation we need to
handle the various video formats.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 89 ++---------
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 49 +------
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 6 +-
drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c | 11 +-
4 files changed, 31 insertions(+), 124 deletions(-)

diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
index 4c79eb64a7a7..cad90d4528f8 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
@@ -10,6 +10,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/fs.h>
+#include <linux/image-formats.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioctl.h>
@@ -497,72 +498,27 @@ static void sun6i_csi_set_format(struct sun6i_csi_dev *sdev)
static void sun6i_csi_set_window(struct sun6i_csi_dev *sdev)
{
struct sun6i_csi_config *config = &sdev->csi.config;
- u32 bytesperline_y;
- u32 bytesperline_c;
+ const struct image_format_info *info =
+ image_format_v4l2_lookup(config->pixelformat);
int *planar_offset = sdev->planar_offset;
- u32 width = config->width;
- u32 height = config->height;
- u32 hor_len = width;
+ u32 bytesperline_y = image_format_info_plane_stride(info, config->width, 0);
+ u32 bytesperline_c = image_format_info_plane_stride(info, config->width, 1);
+ unsigned int offset, i;

- switch (config->pixelformat) {
- case V4L2_PIX_FMT_YUYV:
- case V4L2_PIX_FMT_YVYU:
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_VYUY:
- dev_dbg(sdev->dev,
- "Horizontal length should be 2 times of width for packed YUV formats!\n");
- hor_len = width * 2;
- break;
- default:
- break;
+ offset = 0;
+ for (i = 0; i < info->num_planes; i++) {
+ planar_offset[i] = offset;
+
+ offset += image_format_info_plane_size(info, config->width,
+ config->height, i);
}

regmap_write(sdev->regmap, CSI_CH_HSIZE_REG,
- CSI_CH_HSIZE_HOR_LEN(hor_len) |
+ CSI_CH_HSIZE_HOR_LEN(bytesperline_c) |
CSI_CH_HSIZE_HOR_START(0));
regmap_write(sdev->regmap, CSI_CH_VSIZE_REG,
- CSI_CH_VSIZE_VER_LEN(height) |
+ CSI_CH_VSIZE_VER_LEN(config->height) |
CSI_CH_VSIZE_VER_START(0));
-
- planar_offset[0] = 0;
- switch (config->pixelformat) {
- case V4L2_PIX_FMT_HM12:
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- bytesperline_y = width;
- bytesperline_c = width;
- planar_offset[1] = bytesperline_y * height;
- planar_offset[2] = -1;
- break;
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_YVU420:
- bytesperline_y = width;
- bytesperline_c = width / 2;
- planar_offset[1] = bytesperline_y * height;
- planar_offset[2] = planar_offset[1] +
- bytesperline_c * height / 2;
- break;
- case V4L2_PIX_FMT_YUV422P:
- bytesperline_y = width;
- bytesperline_c = width / 2;
- planar_offset[1] = bytesperline_y * height;
- planar_offset[2] = planar_offset[1] +
- bytesperline_c * height;
- break;
- default: /* raw */
- dev_dbg(sdev->dev,
- "Calculating pixelformat(0x%x)'s bytesperline as a packed format\n",
- config->pixelformat);
- bytesperline_y = (sun6i_csi_get_bpp(config->pixelformat) *
- config->width) / 8;
- bytesperline_c = 0;
- planar_offset[1] = -1;
- planar_offset[2] = -1;
- break;
- }
-
regmap_write(sdev->regmap, CSI_CH_BUF_LEN_REG,
CSI_CH_BUF_LEN_BUF_LEN_C(bytesperline_c) |
CSI_CH_BUF_LEN_BUF_LEN_Y(bytesperline_y));
@@ -588,15 +544,16 @@ int sun6i_csi_update_config(struct sun6i_csi *csi,
void sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr)
{
struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+ struct sun6i_csi_config *config = &sdev->csi.config;
+ const struct image_format_info *info =
+ image_format_v4l2_lookup(config->pixelformat);
+ unsigned int i;
+
+ for (i = 0; i < info->num_planes; i++) {
+ regmap_write(sdev->regmap, CSI_CH_BUF_REG(i, 0),
+ (addr + sdev->planar_offset[i]) >> 2);

- regmap_write(sdev->regmap, CSI_CH_F0_BUFA_REG,
- (addr + sdev->planar_offset[0]) >> 2);
- if (sdev->planar_offset[1] != -1)
- regmap_write(sdev->regmap, CSI_CH_F1_BUFA_REG,
- (addr + sdev->planar_offset[1]) >> 2);
- if (sdev->planar_offset[2] != -1)
- regmap_write(sdev->regmap, CSI_CH_F2_BUFA_REG,
- (addr + sdev->planar_offset[2]) >> 2);
+ }
}

void sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
index c626821aaedb..f3472d8821ab 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
@@ -86,53 +86,4 @@ void sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr);
*/
void sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable);

-/* get bpp form v4l2 pixformat */
-static inline int sun6i_csi_get_bpp(unsigned int pixformat)
-{
- switch (pixformat) {
- case V4L2_PIX_FMT_SBGGR8:
- case V4L2_PIX_FMT_SGBRG8:
- case V4L2_PIX_FMT_SGRBG8:
- case V4L2_PIX_FMT_SRGGB8:
- case V4L2_PIX_FMT_JPEG:
- return 8;
- case V4L2_PIX_FMT_SBGGR10:
- case V4L2_PIX_FMT_SGBRG10:
- case V4L2_PIX_FMT_SGRBG10:
- case V4L2_PIX_FMT_SRGGB10:
- return 10;
- case V4L2_PIX_FMT_SBGGR12:
- case V4L2_PIX_FMT_SGBRG12:
- case V4L2_PIX_FMT_SGRBG12:
- case V4L2_PIX_FMT_SRGGB12:
- case V4L2_PIX_FMT_HM12:
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_YVU420:
- return 12;
- case V4L2_PIX_FMT_YUYV:
- case V4L2_PIX_FMT_YVYU:
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_VYUY:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- case V4L2_PIX_FMT_YUV422P:
- case V4L2_PIX_FMT_RGB565:
- case V4L2_PIX_FMT_RGB565X:
- return 16;
- case V4L2_PIX_FMT_RGB24:
- case V4L2_PIX_FMT_BGR24:
- return 24;
- case V4L2_PIX_FMT_RGB32:
- case V4L2_PIX_FMT_BGR32:
- return 32;
- default:
- WARN(1, "Unsupported pixformat: 0x%x\n", pixformat);
- break;
- }
-
- return 0;
-}
-
#endif /* __SUN6I_CSI_H__ */
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
index 703fa14bb313..7c19d2bcbd7c 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
@@ -74,11 +74,7 @@
#define CSI_CH_SCALE_REG 0x4c
#define CSI_CH_SCALE_QUART_EN BIT(0)

-#define CSI_CH_F0_BUFA_REG 0x50
-
-#define CSI_CH_F1_BUFA_REG 0x58
-
-#define CSI_CH_F2_BUFA_REG 0x60
+#define CSI_CH_BUF_REG(plane, chan) (0x50 + (plane) * 8 + (chan) * 4)

#define CSI_CH_STA_REG 0x6c
#define CSI_CH_STA_FIELD_STA_MASK BIT(2)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
index f0dfe68486d1..0c783140c3a0 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
@@ -5,6 +5,7 @@
* Author: Yong Deng <[email protected]>
*/

+#include <linux/image-formats.h>
#include <linux/of.h>

#include <media/v4l2-device.h>
@@ -351,17 +352,19 @@ static int sun6i_video_try_fmt(struct sun6i_video *video,
struct v4l2_format *f)
{
struct v4l2_pix_format *pixfmt = &f->fmt.pix;
- int bpp;
+ const struct image_format_info *info;

if (!is_pixformat_valid(pixfmt->pixelformat))
pixfmt->pixelformat = supported_pixformats[0];

+ info = image_format_v4l2_lookup(pixfmt->pixelformat);
+
v4l_bound_align_image(&pixfmt->width, MIN_WIDTH, MAX_WIDTH, 1,
&pixfmt->height, MIN_HEIGHT, MAX_WIDTH, 1, 1);

- bpp = sun6i_csi_get_bpp(pixfmt->pixelformat);
- pixfmt->bytesperline = (pixfmt->width * bpp) >> 3;
- pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+ pixfmt->bytesperline = image_format_info_plane_stride(info, pixfmt->width, 0);
+ pixfmt->sizeimage = image_format_info_plane_size(info, pixfmt->width,
+ pixfmt->height, 0);

if (pixfmt->field == V4L2_FIELD_ANY)
pixfmt->field = V4L2_FIELD_NONE;
--
git-series 0.9.1

2019-04-17 07:56:59

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 10/20] drm/exynos: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/exynos/exynos_drm_ipp.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_ipp.h | 4 +++-
drivers/gpu/drm/exynos/exynos_drm_scaler.c | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 23226a0212e8..ba012840fe07 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -562,7 +562,7 @@ static int exynos_drm_ipp_check_format(struct exynos_drm_ipp_task *task,
if (buf->buf.width == 0 || buf->buf.height == 0)
return -EINVAL;

- buf->format = drm_format_info(buf->buf.fourcc);
+ buf->format = image_format_drm_lookup(buf->buf.fourcc);
for (i = 0; i < buf->format->num_planes; i++) {
unsigned int width = (i == 0) ? buf->buf.width :
DIV_ROUND_UP(buf->buf.width, buf->format->hsub);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index 0b27d4a9bf94..c6cd21f185e6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -71,12 +71,14 @@ struct exynos_drm_ipp {
wait_queue_head_t done_wq;
};

+struct image_format_info;
+
struct exynos_drm_ipp_buffer {
struct drm_exynos_ipp_task_buffer buf;
struct drm_exynos_ipp_task_rect rect;

struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
- const struct drm_format_info *format;
+ const struct image_format_info *format;
dma_addr_t dma_addr[MAX_FB_BUFFER];
};

diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index ed1dd1aec902..c9791a2013cf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/component.h>
#include <linux/err.h>
+#include <linux/image-formats.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -301,7 +302,7 @@ static inline void scaler_set_rotation(struct scaler_context *scaler,
}

static inline void scaler_set_csc(struct scaler_context *scaler,
- const struct drm_format_info *fmt)
+ const struct image_format_info *fmt)
{
static const u32 csc_mtx[2][3][3] = {
{ /* YCbCr to RGB */
--
git-series 0.9.1

2019-04-17 07:57:04

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 12/20] drm/ipuv3: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/ipu-v3/ipu-pre.c | 3 ++-
drivers/gpu/ipu-v3/ipu-prg.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
index 6cacfd61d984..83bfcaefe1d3 100644
--- a/drivers/gpu/ipu-v3/ipu-pre.c
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/genalloc.h>
+#include <linux/image-formats.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -174,7 +175,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
unsigned int height, unsigned int stride, u32 format,
uint64_t modifier, unsigned int bufaddr)
{
- const struct drm_format_info *info = drm_format_info(format);
+ const struct image_format_info *info = image_format_drm_lookup(format);
u32 active_bpp = info->cpp[0] >> 1;
u32 val;

diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c
index 94b76badf677..042c141ad07e 100644
--- a/drivers/gpu/ipu-v3/ipu-prg.c
+++ b/drivers/gpu/ipu-v3/ipu-prg.c
@@ -14,6 +14,7 @@
#include <drm/drm_fourcc.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/image-formats.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@@ -132,7 +133,7 @@ EXPORT_SYMBOL_GPL(ipu_prg_present);
bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
uint64_t modifier)
{
- const struct drm_format_info *info = drm_format_info(format);
+ const struct image_format_info *info = image_format_drm_lookup(format);

if (info->num_planes != 1)
return false;
--
git-series 0.9.1

2019-04-17 07:57:22

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 14/20] drm/omap: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +++++----
drivers/gpu/drm/omapdrm/omap_fb.c | 7 ++++---
2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index ba82d916719c..bf60d49ad6ca 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -25,6 +25,7 @@
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/clk.h>
+#include <linux/image-formats.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/seq_file.h>
@@ -1898,9 +1899,9 @@ static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
bool chroma_upscale = plane != OMAP_DSS_WB;
- const struct drm_format_info *info;
+ const struct image_format_info *info;

- info = drm_format_info(fourcc);
+ info = image_format_drm_lookup(fourcc);

if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
return;
@@ -2623,9 +2624,9 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
- const struct drm_format_info *info;
+ const struct image_format_info *info;

- info = drm_format_info(fourcc);
+ info = image_format_drm_lookup(fourcc);

/* when setting up WB, dispc_plane_pclk_rate() returns 0 */
if (plane == OMAP_DSS_WB)
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 1d4143adf829..8caecfc8d1db 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

+#include <linux/image-formats.h>
#include <linux/seq_file.h>

#include <drm/drm_crtc.h>
@@ -60,7 +61,7 @@ struct plane {
struct omap_framebuffer {
struct drm_framebuffer base;
int pin_count;
- const struct drm_format_info *format;
+ const struct image_format_info *format;
struct plane planes[2];
/* lock for pinning (pin_count and planes.dma_addr) */
struct mutex lock;
@@ -72,7 +73,7 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
};

static u32 get_linear_addr(struct drm_framebuffer *fb,
- const struct drm_format_info *format, int n, int x, int y)
+ const struct image_format_info *format, int n, int x, int y)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
struct plane *plane = &omap_fb->planes[n];
@@ -126,7 +127,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
struct drm_plane_state *state, struct omap_overlay_info *info)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- const struct drm_format_info *format = omap_fb->format;
+ const struct image_format_info *format = omap_fb->format;
struct plane *plane = &omap_fb->planes[0];
u32 x, y, orient = 0;

--
git-series 0.9.1

2019-04-17 07:57:26

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 02/20] drm: Remove users of drm_format_(horz|vert)_chroma_subsampling

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 <[email protected]>
Reviewed-by: Paul Kocialkowski <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/arm/malidp_planes.c | 6 +--
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 9 +----
drivers/gpu/drm/drm_fourcc.c | 34 +------------------
drivers/gpu/drm/imx/ipuv3-plane.c | 15 +++-----
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 9 +----
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 24 +++++--------
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +-
drivers/gpu/drm/msm/msm_fb.c | 8 +---
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 9 +----
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++-----
drivers/gpu/drm/tegra/fb.c | 9 +----
drivers/gpu/drm/vc4/vc4_plane.c | 13 ++-----
include/drm/drm_fourcc.h | 2 +-
13 files changed, 39 insertions(+), 114 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index d42e0ea9a303..8f89813d08c1 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -233,8 +233,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,
}
}

- if ((drm_format_horz_chroma_subsampling(format) != 1) ||
- (drm_format_vert_chroma_subsampling(format) != 1)) {
+ if ((info->hsub != 1) || (info->vsub != 1)) {
if (!(format == DRM_FORMAT_YUV420_10BIT &&
(map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
@@ -244,8 +243,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,
}

if (modifier & AFBC_CBR) {
- if ((drm_format_horz_chroma_subsampling(format) == 1) ||
- (drm_format_vert_chroma_subsampling(format) == 1)) {
+ if ((info->hsub == 1) || (info->vsub == 1)) {
DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
return false;
}
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index e836e2de35ce..fdd607ad27fe 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -603,8 +603,6 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
const struct drm_display_mode *mode;
struct drm_crtc_state *crtc_state;
unsigned int tmp;
- int hsub = 1;
- int vsub = 1;
int ret;
int i;

@@ -642,13 +640,10 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)
return -EINVAL;

- hsub = drm_format_horz_chroma_subsampling(fb->format->format);
- vsub = drm_format_vert_chroma_subsampling(fb->format->format);
-
for (i = 0; i < state->nplanes; i++) {
unsigned int offset = 0;
- int xdiv = i ? hsub : 1;
- int ydiv = i ? vsub : 1;
+ int xdiv = i ? fb->format->hsub : 1;
+ int ydiv = i ? fb->format->vsub : 1;

state->bpp[i] = fb->format->cpp[i];
if (!state->bpp[i])
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 873c0001d8c8..e4a2c8372c8b 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -353,40 +353,6 @@ int drm_format_plane_cpp(uint32_t format, int plane)
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)
-{
- const struct drm_format_info *info;
-
- info = drm_format_info(format);
- return info ? info->hsub : 1;
-}
-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)
-{
- const struct drm_format_info *info;
-
- info = drm_format_info(format);
- return info ? info->vsub : 1;
-}
-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
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index d81b3102b488..4a54a5c192d2 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -115,8 +115,8 @@ drm_plane_state_to_ubo(struct drm_plane_state *state)
cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
BUG_ON(!cma_obj);

- x /= drm_format_horz_chroma_subsampling(fb->format->format);
- y /= drm_format_vert_chroma_subsampling(fb->format->format);
+ x /= fb->format->hsub;
+ y /= fb->format->vsub;

return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
fb->format->cpp[1] * x - eba;
@@ -134,8 +134,8 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
BUG_ON(!cma_obj);

- x /= drm_format_horz_chroma_subsampling(fb->format->format);
- y /= drm_format_vert_chroma_subsampling(fb->format->format);
+ x /= fb->format->hsub;
+ y /= fb->format->vsub;

return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
fb->format->cpp[2] * x - eba;
@@ -352,7 +352,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
struct drm_framebuffer *old_fb = old_state->fb;
unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
- int hsub, vsub;
int ret;

/* Ok to disable */
@@ -471,10 +470,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
* The x/y offsets must be even in case of horizontal/vertical
* chroma subsampling.
*/
- hsub = drm_format_horz_chroma_subsampling(fb->format->format);
- vsub = drm_format_vert_chroma_subsampling(fb->format->format);
- if (((state->src.x1 >> 16) & (hsub - 1)) ||
- ((state->src.y1 >> 16) & (vsub - 1)))
+ if (((state->src.x1 >> 16) & (fb->format->hsub - 1)) ||
+ ((state->src.y1 >> 16) & (fb->format->vsub - 1)))
return -EINVAL;
break;
case DRM_FORMAT_RGB565_A8:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index da1f727d7495..7994de952353 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -557,14 +557,9 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
struct dpu_plane_state *pstate,
const struct dpu_format *fmt, bool color_fill)
{
- uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
+ const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format);

/* don't chroma subsample if decimating */
- chroma_subsmpl_h =
- drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
- chroma_subsmpl_v =
- drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
-
/* update scaler. calculate default config for QSEED3 */
_dpu_plane_setup_scaler3(pdpu, pstate,
drm_rect_width(&pdpu->pipe_cfg.src_rect),
@@ -572,7 +567,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
drm_rect_width(&pdpu->pipe_cfg.dst_rect),
drm_rect_height(&pdpu->pipe_cfg.dst_rect),
&pstate->scaler3_cfg, fmt,
- chroma_subsmpl_h, chroma_subsmpl_v);
+ info->hsub, info->vsub);
}

/**
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index be13140967b4..9d9fb6c5fd68 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -650,10 +650,10 @@ static int calc_scalex_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasex_steps[COMP_MAX])
{
+ const struct drm_format_info *info = drm_format_info(pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
uint32_t phasex_step;
- unsigned int hsub;
int ret;

ret = calc_phase_step(src, dest, &phasex_step);
@@ -662,11 +662,9 @@ static int calc_scalex_steps(struct drm_plane *plane,
return ret;
}

- hsub = drm_format_horz_chroma_subsampling(pixel_format);
-
phasex_steps[COMP_0] = phasex_step;
phasex_steps[COMP_3] = phasex_step;
- phasex_steps[COMP_1_2] = phasex_step / hsub;
+ phasex_steps[COMP_1_2] = phasex_step / info->hsub;

return 0;
}
@@ -675,10 +673,10 @@ static int calc_scaley_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasey_steps[COMP_MAX])
{
+ const struct drm_format_info *info = drm_format_info(pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
uint32_t phasey_step;
- unsigned int vsub;
int ret;

ret = calc_phase_step(src, dest, &phasey_step);
@@ -687,11 +685,9 @@ static int calc_scaley_steps(struct drm_plane *plane,
return ret;
}

- vsub = drm_format_vert_chroma_subsampling(pixel_format);
-
phasey_steps[COMP_0] = phasey_step;
phasey_steps[COMP_3] = phasey_step;
- phasey_steps[COMP_1_2] = phasey_step / vsub;
+ phasey_steps[COMP_1_2] = phasey_step / info->vsub;

return 0;
}
@@ -699,8 +695,9 @@ static int calc_scaley_steps(struct drm_plane *plane,
static uint32_t get_scale_config(const struct mdp_format *format,
uint32_t src, uint32_t dst, bool horz)
{
+ const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
bool scaling = format->is_yuv ? true : (src != dst);
- uint32_t sub, pix_fmt = format->base.pixel_format;
+ uint32_t sub;
uint32_t ya_filter, uv_filter;
bool yuv = format->is_yuv;

@@ -708,8 +705,7 @@ static uint32_t get_scale_config(const struct mdp_format *format,
return 0;

if (yuv) {
- sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) :
- drm_format_vert_chroma_subsampling(pix_fmt);
+ sub = horz ? info->hsub : info->vsub;
uv_filter = ((src / sub) <= dst) ?
SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
}
@@ -754,7 +750,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
{
- uint32_t pix_fmt = format->base.pixel_format;
+ const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
uint32_t lr, tb, req;
int i;

@@ -763,8 +759,8 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
uint32_t roi_h = src_h;

if (format->is_yuv && i == COMP_1_2) {
- roi_w /= drm_format_horz_chroma_subsampling(pix_fmt);
- roi_h /= drm_format_vert_chroma_subsampling(pix_fmt);
+ roi_w /= info->hsub;
+ roi_h /= info->vsub;
}

lr = (pe_left[i] >= 0) ?
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index 72ab8d89efa4..b30b2f4efc60 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -135,7 +135,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
uint32_t blkcfg = 0;

nplanes = info->num_planes;
- hsub = drm_format_horz_chroma_subsampling(fmt);
+ hsub = info->hsub;

/* different if BWC (compressed framebuffer?) enabled: */
nlines = 2;
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 432beddafb9e..f69c0afd6ec6 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -145,16 +145,12 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
struct drm_framebuffer *fb;
const struct msm_format *format;
int ret, i, n;
- unsigned int hsub, vsub;

DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
dev, mode_cmd, mode_cmd->width, mode_cmd->height,
(char *)&mode_cmd->pixel_format);

n = info->num_planes;
- hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
- vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
-
format = kms->funcs->get_format(kms, mode_cmd->pixel_format,
mode_cmd->modifier[0]);
if (!format) {
@@ -180,8 +176,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
}

for (i = 0; i < n; i++) {
- unsigned int width = mode_cmd->width / (i ? hsub : 1);
- unsigned int height = mode_cmd->height / (i ? vsub : 1);
+ unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
+ unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
unsigned int min_size;

min_size = (height - 1) * mode_cmd->pitches[i]
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 606d176d5d96..c318fae28581 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -79,18 +79,13 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
struct drm_framebuffer *fb;
struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
struct drm_gem_object *obj;
- unsigned int hsub;
- unsigned int vsub;
int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER);
int ret;
int i;

- hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
- vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
-
for (i = 0; i < num_planes; i++) {
- unsigned int width = mode_cmd->width / (i ? hsub : 1);
- unsigned int height = mode_cmd->height / (i ? vsub : 1);
+ unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
+ unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
unsigned int min_size;

obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 20a9c296d027..345d5cb5e956 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -317,21 +317,18 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
uint32_t src_w, uint32_t src_h, uint32_t dst_w,
uint32_t dst_h, uint32_t pixel_format)
{
+ const struct drm_format_info *info = drm_format_info(pixel_format);
uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
uint16_t cbcr_hor_scl_mode = SCALE_NONE;
uint16_t cbcr_ver_scl_mode = SCALE_NONE;
- int hsub = drm_format_horz_chroma_subsampling(pixel_format);
- int vsub = drm_format_vert_chroma_subsampling(pixel_format);
- const struct drm_format_info *info;
bool is_yuv = false;
- uint16_t cbcr_src_w = src_w / hsub;
- uint16_t cbcr_src_h = src_h / vsub;
+ uint16_t cbcr_src_w = src_w / info->hsub;
+ uint16_t cbcr_src_h = src_h / info->vsub;
uint16_t vsu_mode;
uint16_t lb_mode;
uint32_t val;
int vskiplines;

- info = drm_format_info(pixel_format);

if (info->is_yuv)
is_yuv = true;
@@ -831,8 +828,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
(state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);

if (is_yuv) {
- int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
- int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
+ int hsub = fb->format->hsub;
+ int vsub = fb->format->vsub;
int bpp = fb->format->cpp[1];

uv_obj = fb->obj[1];
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index da0747e317b7..94fb75089d87 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -132,18 +132,15 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
const struct drm_mode_fb_cmd2 *cmd)
{
const struct drm_format_info *info = drm_get_format_info(drm, cmd);
- unsigned int hsub, vsub, i;
struct tegra_bo *planes[4];
struct drm_gem_object *gem;
struct drm_framebuffer *fb;
+ unsigned int i;
int err;

- hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
- vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);
-
for (i = 0; i < info->num_planes; i++) {
- unsigned int width = cmd->width / (i ? hsub : 1);
- unsigned int height = cmd->height / (i ? vsub : 1);
+ unsigned int width = cmd->width / (i ? info->hsub : 1);
+ unsigned int height = cmd->height / (i ? info->vsub : 1);
unsigned int size, bpp;

gem = drm_gem_object_lookup(file, cmd->handles[i]);
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index e3c0a350cb77..be2274924b34 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -310,10 +310,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
struct drm_framebuffer *fb = state->fb;
struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
u32 subpixel_src_mask = (1 << 16) - 1;
- u32 format = fb->format->format;
int num_planes = fb->format->num_planes;
struct drm_crtc_state *crtc_state;
- u32 h_subsample, v_subsample;
+ u32 h_subsample = fb->format->hsub;
+ u32 v_subsample = fb->format->vsub;
int i, ret;

crtc_state = drm_atomic_get_existing_crtc_state(state->state,
@@ -328,9 +328,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
if (ret)
return ret;

- h_subsample = drm_format_horz_chroma_subsampling(format);
- v_subsample = drm_format_vert_chroma_subsampling(format);
-
for (i = 0; i < num_planes; i++)
vc4_state->offsets[i] = bo->paddr + fb->offsets[i];

@@ -593,7 +590,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
int num_planes = fb->format->num_planes;
- u32 h_subsample, v_subsample;
+ u32 h_subsample = fb->format->hsub;
+ u32 v_subsample = fb->format->vsub;
bool mix_plane_alpha;
bool covers_screen;
u32 scl0, scl1, pitch0;
@@ -623,9 +621,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
scl1 = vc4_get_scl_field(state, 0);
}

- h_subsample = drm_format_horz_chroma_subsampling(format->drm);
- v_subsample = drm_format_vert_chroma_subsampling(format->drm);
-
rotation = drm_rotation_simplify(state->rotation,
DRM_MODE_ROTATE_0 |
DRM_MODE_REFLECT_X |
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 41779b327d91..eeec449d6c6a 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -269,8 +269,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
uint32_t bpp, uint32_t depth);
int drm_format_plane_cpp(uint32_t format, int plane);
-int drm_format_horz_chroma_subsampling(uint32_t format);
-int drm_format_vert_chroma_subsampling(uint32_t format);
int drm_format_plane_width(int width, uint32_t format, int plane);
int drm_format_plane_height(int height, uint32_t format, int plane);
unsigned int drm_format_info_block_width(const struct drm_format_info *info,
--
git-series 0.9.1

2019-04-17 07:57:32

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 04/20] drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height

So far, the drm_format_plane_height/width functions were operating on the
format's fourcc and was doing a lookup to retrieve the drm_format_info
structure and return the cpp.

However, this is inefficient since in most cases, we will have the
drm_format_info pointer already available so we shouldn't have to perform a
new lookup. Some drm_fourcc functions also already operate on the
drm_format_info pointer for that reason, so the API is quite inconsistent
there.

Let's follow the latter pattern and remove the extra lookup while being a
bit more consistent.

In order to be extra consistent, also rename that function to
drm_format_info_plane_cpp and to a static function in the header to match
the current policy. The parameters order have also be changed to match the
other functions prototype.

Reviewed-by: Emil Velikov <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/drm_fourcc.c | 48 +----------------------------
drivers/gpu/drm/meson/meson_overlay.c | 12 +++----
include/drm/drm_fourcc.h | 46 +++++++++++++++++++++++++--
3 files changed, 50 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 5f63fc74e265..35b459d186c5 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -333,54 +333,6 @@ drm_get_format_info(struct drm_device *dev,
EXPORT_SYMBOL(drm_get_format_info);

/**
- * 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
diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index fb8515b2860c..55b3f2f2e608 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -466,8 +466,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2];
priv->viu.vd1_stride2 = fb->pitches[2];
priv->viu.vd1_height2 =
- drm_format_plane_height(fb->height,
- fb->format->format, 2);
+ drm_format_info_plane_height(fb->format,
+ fb->height, 2);
DRM_DEBUG("plane 2 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr2,
priv->viu.vd1_stride2,
@@ -478,8 +478,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1];
priv->viu.vd1_stride1 = fb->pitches[1];
priv->viu.vd1_height1 =
- drm_format_plane_height(fb->height,
- fb->format->format, 1);
+ drm_format_info_plane_height(fb->format,
+ fb->height, 1);
DRM_DEBUG("plane 1 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr1,
priv->viu.vd1_stride1,
@@ -490,8 +490,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0];
priv->viu.vd1_stride0 = fb->pitches[0];
priv->viu.vd1_height0 =
- drm_format_plane_height(fb->height,
- fb->format->format, 0);
+ drm_format_info_plane_height(fb->format,
+ fb->height, 0);
DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr0,
priv->viu.vd1_stride0,
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 6b5a82b31bc4..4ef8ccb5d236 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -277,6 +277,50 @@ int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane)
return info->cpp[plane];
}

+/**
+ * drm_format_info_plane_width - width of the plane given the first plane
+ * @format: pixel format info
+ * @width: width of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The width of @plane, given that the width of the first plane is @width.
+ */
+static inline
+int drm_format_info_plane_width(const struct drm_format_info *info, int width,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return width;
+
+ return width / info->hsub;
+}
+
+/**
+ * drm_format_info_plane_height - height of the plane given the first plane
+ * @format: pixel format info
+ * @height: height of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The height of @plane, given that the height of the first plane is @height.
+ */
+static inline
+int drm_format_info_plane_height(const struct drm_format_info *info, int height,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return height;
+
+ return height / info->vsub;
+}
+
const struct drm_format_info *__drm_format_info(u32 format);
const struct drm_format_info *drm_format_info(u32 format);
const struct drm_format_info *
@@ -285,8 +329,6 @@ drm_get_format_info(struct drm_device *dev,
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
uint32_t bpp, uint32_t depth);
-int drm_format_plane_width(int width, uint32_t format, int plane);
-int drm_format_plane_height(int height, uint32_t format, int plane);
unsigned int drm_format_info_block_width(const struct drm_format_info *info,
int plane);
unsigned int drm_format_info_block_height(const struct drm_format_info *info,
--
git-series 0.9.1

2019-04-17 07:57:33

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 06/20] lib: Add video format information library

Move the DRM formats API to turn this into a more generic image formats API
to be able to leverage it into some other places of the kernel, such as
v4l2 drivers.

Signed-off-by: Maxime Ripard <[email protected]>
---
include/linux/image-formats.h | 387 +++++++++++++++++++++-
lib/Kconfig | 7 +-
lib/Makefile | 3 +-
lib/image-formats-selftests.c | 325 +++++++++++++++++-
lib/image-formats.c | 655 +++++++++++++++++++++++++++++++++++-
5 files changed, 1377 insertions(+)
create mode 100644 include/linux/image-formats.h
create mode 100644 lib/image-formats-selftests.c
create mode 100644 lib/image-formats.c

diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
new file mode 100644
index 000000000000..ec43d9f9a527
--- /dev/null
+++ b/include/linux/image-formats.h
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2016 Laurent Pinchart <[email protected]>
+ * Copyright (c) 2019 Maxime Ripard <[email protected]>
+ *
+ * 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.
+ */
+
+#ifndef _IMAGE_FORMATS_H_
+#define _IMAGE_FORMATS_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/**
+ * struct image_format_info - information about a image format
+ */
+struct image_format_info {
+ union {
+ /**
+ * @drm_fmt:
+ *
+ * DRM 4CC format identifier (DRM_FORMAT_*)
+ */
+ u32 drm_fmt;
+
+ /**
+ * @format:
+ *
+ * DRM 4CC format identifier (DRM_FORMAT_*). Kept
+ * around for compatibility reasons with the current
+ * DRM drivers.
+ */
+ u32 format;
+ };
+
+ /**
+ * @depth:
+ *
+ * Color depth (number of bits per pixel excluding padding bits),
+ * valid for a subset of RGB formats only. This is a legacy field, do
+ * not use in new code and set to 0 for new formats.
+ */
+ u8 depth;
+
+ /** @num_planes: Number of color planes (1 to 3) */
+ u8 num_planes;
+
+ union {
+ /**
+ * @cpp:
+ *
+ * Number of bytes per pixel (per plane), this is aliased with
+ * @char_per_block. It is deprecated in favour of using the
+ * triplet @char_per_block, @block_w, @block_h for better
+ * describing the pixel format.
+ */
+ u8 cpp[3];
+
+ /**
+ * @char_per_block:
+ *
+ * Number of bytes per block (per plane), where blocks are
+ * defined as a rectangle of pixels which are stored next to
+ * each other in a byte aligned memory region. Together with
+ * @block_w and @block_h this is used to properly describe tiles
+ * in tiled formats or to describe groups of pixels in packed
+ * formats for which the memory needed for a single pixel is not
+ * byte aligned.
+ *
+ * @cpp has been kept for historical reasons because there are
+ * a lot of places in drivers where it's used. In drm core for
+ * generic code paths the preferred way is to use
+ * @char_per_block, image_format_info_block_width() and
+ * image_format_info_block_height() which allows handling both
+ * block and non-block formats in the same way.
+ *
+ * For formats that are intended to be used only with non-linear
+ * modifiers both @cpp and @char_per_block must be 0 in the
+ * generic format table. Drivers could supply accurate
+ * information from their drm_mode_config.get_format_info hook
+ * if they want the core to be validating the pitch.
+ */
+ u8 char_per_block[3];
+ };
+
+ /**
+ * @block_w:
+ *
+ * Block width in pixels, this is intended to be accessed through
+ * image_format_info_block_width()
+ */
+ u8 block_w[3];
+
+ /**
+ * @block_h:
+ *
+ * Block height in pixels, this is intended to be accessed through
+ * image_format_info_block_height()
+ */
+ u8 block_h[3];
+
+ /** @hsub: Horizontal chroma subsampling factor */
+ u8 hsub;
+ /** @vsub: Vertical chroma subsampling factor */
+ u8 vsub;
+
+ /** @has_alpha: Does the format embeds an alpha component? */
+ bool has_alpha;
+
+ /** @is_yuv: Is it a YUV format? */
+ bool is_yuv;
+};
+
+/**
+ * image_format_info_is_yuv_packed - check that the format info matches a YUV
+ * format with data laid in a single plane
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a packed YUV format.
+ */
+static inline bool
+image_format_info_is_yuv_packed(const struct image_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 1;
+}
+
+/**
+ * image_format_info_is_yuv_semiplanar - check that the format info matches a YUV
+ * format with data laid in two planes (luminance and chrominance)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a semiplanar YUV format.
+ */
+static inline bool
+image_format_info_is_yuv_semiplanar(const struct image_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 2;
+}
+
+/**
+ * image_format_info_is_yuv_planar - check that the format info matches a YUV
+ * format with data laid in three planes (one for each YUV component)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a planar YUV format.
+ */
+static inline bool
+image_format_info_is_yuv_planar(const struct image_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 3;
+}
+
+/**
+ * image_format_info_is_yuv_sampling_410 - check that the format info matches a
+ * YUV format with 4:1:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:0
+ * sub-sampling.
+ */
+static inline bool
+image_format_info_is_yuv_sampling_410(const struct image_format_info *info)
+{
+ return info->is_yuv && info->hsub == 4 && info->vsub == 4;
+}
+
+/**
+ * image_format_info_is_yuv_sampling_411 - check that the format info matches a
+ * YUV format with 4:1:1 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:1
+ * sub-sampling.
+ */
+static inline bool
+image_format_info_is_yuv_sampling_411(const struct image_format_info *info)
+{
+ return info->is_yuv && info->hsub == 4 && info->vsub == 1;
+}
+
+/**
+ * image_format_info_is_yuv_sampling_420 - check that the format info matches a
+ * YUV format with 4:2:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:0
+ * sub-sampling.
+ */
+static inline bool
+image_format_info_is_yuv_sampling_420(const struct image_format_info *info)
+{
+ return info->is_yuv && info->hsub == 2 && info->vsub == 2;
+}
+
+/**
+ * image_format_info_is_yuv_sampling_422 - check that the format info matches a
+ * YUV format with 4:2:2 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:2
+ * sub-sampling.
+ */
+static inline bool
+image_format_info_is_yuv_sampling_422(const struct image_format_info *info)
+{
+ return info->is_yuv && info->hsub == 2 && info->vsub == 1;
+}
+
+/**
+ * image_format_info_is_yuv_sampling_444 - check that the format info matches a
+ * YUV format with 4:4:4 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:4:4
+ * sub-sampling.
+ */
+static inline bool
+image_format_info_is_yuv_sampling_444(const struct image_format_info *info)
+{
+ return info->is_yuv && info->hsub == 1 && info->vsub == 1;
+}
+
+/**
+ * image_format_info_plane_cpp - determine the bytes per pixel value
+ * @format: pixel format info
+ * @plane: plane index
+ *
+ * Returns:
+ * The bytes per pixel value for the specified plane.
+ */
+static inline
+int image_format_info_plane_cpp(const struct image_format_info *info, int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ return info->cpp[plane];
+}
+
+/**
+ * image_format_info_plane_width - width of the plane given the first plane
+ * @format: pixel format info
+ * @width: width of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The width of @plane, given that the width of the first plane is @width.
+ */
+static inline
+int image_format_info_plane_width(const struct image_format_info *info, int width,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return width;
+
+ return width / info->hsub;
+}
+
+/**
+ * image_format_info_plane_height - height of the plane given the first plane
+ * @format: pixel format info
+ * @height: height of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The height of @plane, given that the height of the first plane is @height.
+ */
+static inline
+int image_format_info_plane_height(const struct image_format_info *info, int height,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return height;
+
+ return height / info->vsub;
+}
+
+/**
+ * image_format_info_block_width - width in pixels of block.
+ * @format: pointer to the image_format_info
+ * @plane: plane index
+ *
+ * Returns:
+ * The width in pixels of a block, depending on the plane index.
+ */
+static inline
+unsigned int image_format_info_block_width(const struct image_format_info *format,
+ int plane)
+{
+ if (!format)
+ return 0;
+
+ if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
+ return 0;
+
+ if (plane >= format->num_planes)
+ return 0;
+
+ if (!format->block_w[plane])
+ return 1;
+
+ return format->block_w[plane];
+}
+
+/**
+ * image_format_info_block_height - height in pixels of a block
+ * @info: pointer to the image_format_info
+ * @plane: plane index
+ *
+ * Returns:
+ * The height in pixels of a block, depending on the plane index.
+ */
+static inline
+unsigned int image_format_info_block_height(const struct image_format_info *format,
+ int plane)
+{
+ if (!format)
+ return 0;
+
+ if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
+ return 0;
+
+ if (plane >= format->num_planes)
+ return 0;
+
+ if (!format->block_h[plane])
+ return 1;
+
+ return format->block_h[plane];
+}
+
+/**
+ * image_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.
+ */
+static inline
+uint64_t image_format_info_min_pitch(const struct image_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],
+ image_format_info_block_width(info, plane) *
+ image_format_info_block_height(info, plane));
+}
+
+const struct image_format_info *__image_format_drm_lookup(u32 drm);
+const struct image_format_info *image_format_drm_lookup(u32 drm);
+
+#endif /* _IMAGE_FORMATS_H_ */
diff --git a/lib/Kconfig b/lib/Kconfig
index fb453afff32e..9a0160d3123b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -625,3 +625,10 @@ config GENERIC_LIB_UCMPDI2

config OBJAGG
tristate "objagg" if COMPILE_TEST
+
+config IMAGE_FORMATS
+ bool
+
+config IMAGE_FORMATS_SELFTESTS
+ tristate "Test image format functions"
+ depends on IMAGE_FORMATS
diff --git a/lib/Makefile b/lib/Makefile
index 6996d2b9f401..203336b91248 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -280,3 +280,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
obj-$(CONFIG_OBJAGG) += objagg.o
+
+obj-$(CONFIG_IMAGE_FORMATS) += image-formats.o
+obj-$(CONFIG_IMAGE_FORMATS_SELFTESTS) += image-formats-selftests.o
diff --git a/lib/image-formats-selftests.c b/lib/image-formats-selftests.c
new file mode 100644
index 000000000000..d0f0011b535e
--- /dev/null
+++ b/lib/image-formats-selftests.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for the image_format functions
+ */
+
+#define pr_fmt(fmt) "image_format: " fmt
+
+#include <linux/errno.h>
+#include <linux/image-formats.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drm_fourcc.h>
+
+#define FAIL(test, msg, ...) \
+ do { \
+ if (test) { \
+ pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ return -EINVAL; \
+ } \
+ } while (0)
+
+#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
+
+static int test_image_format_info_block_width(void)
+{
+ const struct image_format_info *info = NULL;
+
+ /* Test invalid arguments */
+ FAIL_ON(image_format_info_block_width(info, 0) != 0);
+ FAIL_ON(image_format_info_block_width(info, -1) != 0);
+ FAIL_ON(image_format_info_block_width(info, 1) != 0);
+
+ /* Test 1 plane format */
+ info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_width(info, 0) != 1);
+ FAIL_ON(image_format_info_block_width(info, 1) != 0);
+ FAIL_ON(image_format_info_block_width(info, -1) != 0);
+
+ /* Test 2 planes format */
+ info = image_format_drm_lookup(DRM_FORMAT_NV12);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_width(info, 0) != 1);
+ FAIL_ON(image_format_info_block_width(info, 1) != 1);
+ FAIL_ON(image_format_info_block_width(info, 2) != 0);
+ FAIL_ON(image_format_info_block_width(info, -1) != 0);
+
+ /* Test 3 planes format */
+ info = image_format_drm_lookup(DRM_FORMAT_YUV422);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_width(info, 0) != 1);
+ FAIL_ON(image_format_info_block_width(info, 1) != 1);
+ FAIL_ON(image_format_info_block_width(info, 2) != 1);
+ FAIL_ON(image_format_info_block_width(info, 3) != 0);
+ FAIL_ON(image_format_info_block_width(info, -1) != 0);
+
+ /* Test a tiled format */
+ info = image_format_drm_lookup(DRM_FORMAT_X0L0);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_width(info, 0) != 2);
+ FAIL_ON(image_format_info_block_width(info, 1) != 0);
+ FAIL_ON(image_format_info_block_width(info, -1) != 0);
+
+ return 0;
+}
+
+static int test_image_format_info_block_height(void)
+{
+ const struct image_format_info *info = NULL;
+
+ /* Test invalid arguments */
+ FAIL_ON(image_format_info_block_height(info, 0) != 0);
+ FAIL_ON(image_format_info_block_height(info, -1) != 0);
+ FAIL_ON(image_format_info_block_height(info, 1) != 0);
+
+ /* Test 1 plane format */
+ info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_height(info, 0) != 1);
+ FAIL_ON(image_format_info_block_height(info, 1) != 0);
+ FAIL_ON(image_format_info_block_height(info, -1) != 0);
+
+ /* Test 2 planes format */
+ info = image_format_drm_lookup(DRM_FORMAT_NV12);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_height(info, 0) != 1);
+ FAIL_ON(image_format_info_block_height(info, 1) != 1);
+ FAIL_ON(image_format_info_block_height(info, 2) != 0);
+ FAIL_ON(image_format_info_block_height(info, -1) != 0);
+
+ /* Test 3 planes format */
+ info = image_format_drm_lookup(DRM_FORMAT_YUV422);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_height(info, 0) != 1);
+ FAIL_ON(image_format_info_block_height(info, 1) != 1);
+ FAIL_ON(image_format_info_block_height(info, 2) != 1);
+ FAIL_ON(image_format_info_block_height(info, 3) != 0);
+ FAIL_ON(image_format_info_block_height(info, -1) != 0);
+
+ /* Test a tiled format */
+ info = image_format_drm_lookup(DRM_FORMAT_X0L0);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_block_height(info, 0) != 2);
+ FAIL_ON(image_format_info_block_height(info, 1) != 0);
+ FAIL_ON(image_format_info_block_height(info, -1) != 0);
+
+ return 0;
+}
+
+static int test_image_format_info_min_pitch(void)
+{
+ const struct image_format_info *info = NULL;
+
+ /* Test invalid arguments */
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ /* Test 1 plane 8 bits per pixel format */
+ info = image_format_drm_lookup(DRM_FORMAT_RGB332);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX);
+ FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
+ (uint64_t)(UINT_MAX - 1));
+
+ /* Test 1 plane 16 bits per pixel format */
+ info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX * 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
+ (uint64_t)(UINT_MAX - 1) * 2);
+
+ /* Test 1 plane 24 bits per pixel format */
+ info = image_format_drm_lookup(DRM_FORMAT_RGB888);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 3);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 6);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1920);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 3072);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 5760);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 12288);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2013);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX * 3);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
+ (uint64_t)(UINT_MAX - 1) * 3);
+
+ /* Test 1 plane 32 bits per pixel format */
+ info = image_format_drm_lookup(DRM_FORMAT_ABGR8888);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 4);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 8);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 2560);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 4096);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 7680);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 16384);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2684);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX * 4);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
+ (uint64_t)(UINT_MAX - 1) * 4);
+
+ /* Test 2 planes format */
+ info = image_format_drm_lookup(DRM_FORMAT_NV12);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 640);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 1024);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 1920);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 4096);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 672);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX);
+ FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
+ (uint64_t)UINT_MAX + 1);
+ FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
+ (uint64_t)(UINT_MAX - 1));
+ FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
+ (uint64_t)(UINT_MAX - 1));
+
+ /* Test 3 planes 8 bits per pixel format */
+ info = image_format_drm_lookup(DRM_FORMAT_YUV422);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 3, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 1);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 1) != 1);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 2) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 2) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 320);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 320) != 320);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 512);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 512) != 512);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 960);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 960) != 960);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 2048);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 2048) != 2048);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 336);
+ FAIL_ON(image_format_info_min_pitch(info, 2, 336) != 336);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX);
+ FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
+ (uint64_t)UINT_MAX / 2 + 1);
+ FAIL_ON(image_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
+ (uint64_t)UINT_MAX / 2 + 1);
+ FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
+ (uint64_t)(UINT_MAX - 1) / 2);
+ FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
+ (uint64_t)(UINT_MAX - 1) / 2);
+ FAIL_ON(image_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
+ (uint64_t)(UINT_MAX - 1) / 2);
+
+ /* Test tiled format */
+ info = image_format_drm_lookup(DRM_FORMAT_X0L2);
+ FAIL_ON(!info);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
+ FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
+
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
+ FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
+ (uint64_t)UINT_MAX * 2);
+ FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
+ (uint64_t)(UINT_MAX - 1) * 2);
+
+ return 0;
+}
+
+#define selftest(test) { .name = #test, .func = test, }
+
+static struct image_format_test {
+ char *name;
+ int (*func)(void);
+} tests[] = {
+ selftest(test_image_format_info_block_height),
+ selftest(test_image_format_info_block_width),
+ selftest(test_image_format_info_min_pitch),
+};
+
+static int __init image_format_test_init(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ struct image_format_test *test = &tests[i];
+ int ret;
+
+ ret = test->func();
+ if (ret) {
+ pr_err("Failed test %s\n", test->name);
+ return ret;
+ }
+ }
+
+ pr_info("All tests executed properly.\n");
+ return 0;
+}
+module_init(image_format_test_init);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_AUTHOR("Maxime Ripard <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/lib/image-formats.c b/lib/image-formats.c
new file mode 100644
index 000000000000..1e52a7410222
--- /dev/null
+++ b/lib/image-formats.c
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2016 Laurent Pinchart <[email protected]>
+ * Copyright (c) 2019 Maxime Ripard <[email protected]>
+ *
+ * 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/image-formats.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+
+#include <uapi/drm/drm_fourcc.h>
+
+static const struct image_format_info formats[] = {
+ {
+ .drm_fmt = DRM_FORMAT_C8,
+ .depth = 8,
+ .num_planes = 1,
+ .cpp = { 1, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGB332,
+ .depth = 8,
+ .num_planes = 1,
+ .cpp = { 1, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGR233,
+ .depth = 8,
+ .num_planes = 1,
+ .cpp = { 1, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XRGB4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XBGR4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBX4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRX4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_ARGB4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_ABGR4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBA4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRA4444,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_XRGB1555,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XBGR1555,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBX5551,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRX5551,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_ARGB1555,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_ABGR1555,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBA5551,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRA5551,
+ .depth = 15,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGB565,
+ .depth = 16,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGR565,
+ .depth = 16,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGB888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 3, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGR888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 3, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XRGB8888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XBGR8888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBX8888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRX8888,
+ .depth = 24,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGB565_A8,
+ .depth = 24,
+ .num_planes = 2,
+ .cpp = { 2, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGR565_A8,
+ .depth = 24,
+ .num_planes = 2,
+ .cpp = { 2, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_XRGB2101010,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_XBGR2101010,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBX1010102,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRX1010102,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ }, {
+ .drm_fmt = DRM_FORMAT_ARGB2101010,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_ABGR2101010,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBA1010102,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRA1010102,
+ .depth = 30,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_ARGB8888,
+ .depth = 32,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_ABGR8888,
+ .depth = 32,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBA8888,
+ .depth = 32,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRA8888,
+ .depth = 32,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGB888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 3, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGR888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 3, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_XRGB8888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 4, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_XBGR8888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 4, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_RGBX8888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 4, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_BGRX8888_A8,
+ .depth = 32,
+ .num_planes = 2,
+ .cpp = { 4, 1, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUV410,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 4,
+ .vsub = 4,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVU410,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 4,
+ .vsub = 4,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUV411,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 4,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVU411,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 4,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUV420,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 2,
+ .vsub = 2,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVU420,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 2,
+ .vsub = 2,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUV422,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVU422,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUV444,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 1,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVU444,
+ .depth = 0,
+ .num_planes = 3,
+ .cpp = { 1, 1, 1 },
+ .hsub = 1,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV12,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 2,
+ .vsub = 2,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV21,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 2,
+ .vsub = 2,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV16,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV61,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV24,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_NV42,
+ .depth = 0,
+ .num_planes = 2,
+ .cpp = { 1, 2, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YUYV,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_YVYU,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_UYVY,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_VYUY,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 2, 0, 0 },
+ .hsub = 2,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_XYUV8888,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = DRM_FORMAT_AYUV,
+ .depth = 0,
+ .num_planes = 1,
+ .cpp = { 4, 0, 0 },
+ .hsub = 1,
+ .vsub = 1,
+ .has_alpha = true,
+ .is_yuv = true,
+ }, {
+ .drm_fmt = 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,
+ }, {
+ .drm_fmt = 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,
+ }, {
+ .drm_fmt = 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,
+ }, {
+ .drm_fmt = 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,
+ },
+};
+
+#define __image_format_lookup(_field, _fmt) \
+ ({ \
+ const struct image_format_info *format = NULL; \
+ unsigned i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(formats); i++) \
+ if (formats[i]._field == _fmt) \
+ format = &formats[i]; \
+ \
+ format; \
+ })
+
+/**
+ * __image_format_drm_lookup - query information for a given format
+ * @drm: DRM fourcc pixel format (DRM_FORMAT_*)
+ *
+ * The caller should only pass a supported pixel format to this function.
+ *
+ * Returns:
+ * The instance of struct image_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
+ */
+const struct image_format_info *__image_format_drm_lookup(u32 drm)
+{
+ return __image_format_lookup(drm_fmt, drm);
+}
+EXPORT_SYMBOL(__image_format_drm_lookup);
+
+/**
+ * image_format_drm_lookup - query information for a given format
+ * @drm: DRM fourcc 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 image_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
+ */
+const struct image_format_info *image_format_drm_lookup(u32 drm)
+{
+ const struct image_format_info *format;
+
+ format = __image_format_drm_lookup(drm);
+
+ WARN_ON(!format);
+ return format;
+}
+EXPORT_SYMBOL(image_format_drm_lookup);
--
git-series 0.9.1

2019-04-17 07:57:42

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 13/20] drm/msm: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 6 ++++--
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 ++-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 5 +++--
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 9 +++++----
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 5 +++--
5 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index c3d491e8d44b..94fc4330b6de 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -12,6 +12,8 @@

#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__

+#include <linux/image-formats.h>
+
#include <uapi/drm/drm_fourcc.h>

#include "msm_media_info.h"
@@ -1040,7 +1042,7 @@ int dpu_format_check_modified_format(
const struct drm_mode_fb_cmd2 *cmd,
struct drm_gem_object **bos)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
const struct dpu_format *fmt;
struct dpu_hw_fmt_layout layout;
uint32_t bos_total_size = 0;
@@ -1052,7 +1054,7 @@ int dpu_format_check_modified_format(
}

fmt = to_dpu_format(msm_fmt);
- info = drm_format_info(fmt->base.pixel_format);
+ info = image_format_drm_lookup(fmt->base.pixel_format);
if (!info)
return -EINVAL;

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 7994de952353..b22d350c7537 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -20,6 +20,7 @@

#include <linux/debugfs.h>
#include <linux/dma-buf.h>
+#include <linux/image-formats.h>

#include <drm/drm_atomic_uapi.h>

@@ -557,7 +558,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
struct dpu_plane_state *pstate,
const struct dpu_format *fmt, bool color_fill)
{
- const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(fmt->base.pixel_format);

/* don't chroma subsample if decimating */
/* update scaler. calculate default config for QSEED3 */
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index a565dccaba3a..ef71dde2a3b6 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -16,6 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

+#include <linux/image-formats.h>
#include <linux/sort.h>
#include <drm/drm_mode.h>
#include <drm/drm_crtc.h>
@@ -782,7 +783,7 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)

static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
{
- const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ARGB8888);
+ const struct image_format_info *info = image_format_drm_lookup(DRM_FORMAT_ARGB8888);
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
@@ -801,7 +802,7 @@ static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
width = mdp5_crtc->cursor.width;
height = mdp5_crtc->cursor.height;

- stride = width * drm_format_info_plane_cpp(info, 0);
+ stride = width * image_format_info_plane_cpp(info, 0);

get_roi(crtc, &roi_w, &roi_h);

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index 9d9fb6c5fd68..00091637a00c 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -17,6 +17,7 @@
*/

#include <drm/drm_print.h>
+#include <linux/image-formats.h>
#include "mdp5_kms.h"

struct mdp5_plane {
@@ -650,7 +651,7 @@ static int calc_scalex_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasex_steps[COMP_MAX])
{
- const struct drm_format_info *info = drm_format_info(pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
uint32_t phasex_step;
@@ -673,7 +674,7 @@ static int calc_scaley_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasey_steps[COMP_MAX])
{
- const struct drm_format_info *info = drm_format_info(pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
uint32_t phasey_step;
@@ -695,7 +696,7 @@ static int calc_scaley_steps(struct drm_plane *plane,
static uint32_t get_scale_config(const struct mdp_format *format,
uint32_t src, uint32_t dst, bool horz)
{
- const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(format->base.pixel_format);
bool scaling = format->is_yuv ? true : (src != dst);
uint32_t sub;
uint32_t ya_filter, uv_filter;
@@ -750,7 +751,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
{
- const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(format->base.pixel_format);
uint32_t lr, tb, req;
int i;

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index 1ca294694597..05fbf1028c78 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -16,6 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

+#include <linux/image-formats.h>
#include <drm/drm_util.h>

#include "mdp5_kms.h"
@@ -127,7 +128,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
const struct mdp_format *format,
u32 width, bool hdecim)
{
- const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(format->base.pixel_format);
struct mdp5_kms *mdp5_kms = get_kms(smp);
int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
int i, hsub, nplanes, nlines;
@@ -158,7 +159,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
for (i = 0; i < nplanes; i++) {
int n, fetch_stride, cpp;

- cpp = drm_format_info_plane_cpp(info, i);
+ cpp = image_format_info_plane_cpp(info, i);
fetch_stride = width * cpp / (i ? hsub : 1);

n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);
--
git-series 0.9.1

2019-04-17 07:57:45

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 15/20] drm/rockchip: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 345d5cb5e956..bbd82c986b57 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/image-formats.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -317,7 +318,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
uint32_t src_w, uint32_t src_h, uint32_t dst_w,
uint32_t dst_h, uint32_t pixel_format)
{
- const struct drm_format_info *info = drm_format_info(pixel_format);
+ const struct image_format_info *info = image_format_drm_lookup(pixel_format);
uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
uint16_t cbcr_hor_scl_mode = SCALE_NONE;
uint16_t cbcr_ver_scl_mode = SCALE_NONE;
--
git-series 0.9.1

2019-04-17 07:57:54

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 11/20] drm/i915: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/i915/intel_display.c | 4 ++--
drivers/gpu/drm/i915/intel_pm.c | 6 +++---
drivers/gpu/drm/i915/intel_sprite.c | 4 ++--
3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6a0c4f505593..c745e1172dc9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8094,7 +8094,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,

pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
fourcc = i9xx_format_to_fourcc(pixel_format);
- fb->format = drm_format_info(fourcc);
+ fb->format = image_format_drm_lookup(fourcc);

if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
offset = I915_READ(DSPOFFSET(i9xx_plane));
@@ -9194,7 +9194,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,

fourcc = skl_format_to_fourcc(pixel_format,
val & PLANE_CTL_ORDER_RGBX, alpha);
- fb->format = drm_format_info(fourcc);
+ fb->format = image_format_drm_lookup(fourcc);

tiling = val & PLANE_CTL_TILED_MASK;
switch (tiling) {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7357bddf9ad9..3b490ea1baf0 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3928,7 +3928,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
}

static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
- int width, const struct drm_format_info *format,
+ int width, const struct image_format_info *format,
u64 modifier, unsigned int rotation,
u32 plane_pixel_rate, struct skl_wm_params *wp,
int color_plane);
@@ -3949,7 +3949,7 @@ skl_cursor_allocation(const struct intel_crtc_state *crtc_state,
struct skl_wm_params wp;

ret = skl_compute_wm_params(crtc_state, 256,
- drm_format_info(DRM_FORMAT_ARGB8888),
+ image_format_drm_lookup(DRM_FORMAT_ARGB8888),
DRM_FORMAT_MOD_LINEAR,
DRM_MODE_ROTATE_0,
crtc_state->pixel_rate, &wp, 0);
@@ -4644,7 +4644,7 @@ skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate,

static int
skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
- int width, const struct drm_format_info *format,
+ int width, const struct image_format_info *format,
u64 modifier, unsigned int rotation,
u32 plane_pixel_rate, struct skl_wm_params *wp,
int color_plane)
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index e35601b1f878..152b58267671 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -325,8 +325,8 @@ skl_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
- const struct drm_format_info *info = drm_format_info(pixel_format);
- int cpp = drm_format_info_plane_cpp(info, 0);
+ const struct image_format_info *info = image_format_drm_lookup(pixel_format);
+ int cpp = image_format_info_plane_cpp(info, 0);

/*
* "The stride in bytes must not exceed the
--
git-series 0.9.1

2019-04-17 07:57:59

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 08/20] drm/malidp: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/arm/malidp_drv.c | 1 +
drivers/gpu/drm/arm/malidp_hw.c | 4 ++--
drivers/gpu/drm/arm/malidp_planes.c | 6 +++---
3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 9e5240c2d5c7..6fddb70894cb 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -10,6 +10,7 @@
* ARM Mali DP500/DP550/DP650 KMS/DRM driver
*/

+#include <linux/image-formats.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/component.h>
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 1c9e869f4c52..24c01ff458d5 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -382,8 +382,8 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *

int malidp_format_get_bpp(u32 fmt)
{
- const struct drm_format_info *info = drm_format_info(fmt);
- int bpp = drm_format_info_plane_cpp(info, 0) * 8;
+ const struct image_format_info *info = image_format_drm_lookup(fmt);
+ int bpp = image_format_info_plane_cpp(info, 0) * 8;

if (bpp == 0) {
switch (fmt) {
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 9874f98f2aa5..b9d4d7d9a960 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -150,7 +150,7 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p,
bool malidp_format_mod_supported(struct drm_device *drm,
u32 format, u64 modifier)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
const u64 *modifiers;
struct malidp_drm *malidp = drm->dev_private;
const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
@@ -201,7 +201,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,
return false;
}

- info = drm_format_info(format);
+ info = image_format_drm_lookup(format);

if (info->num_planes != 1) {
DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
@@ -227,7 +227,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,

if (modifier & AFBC_SPLIT) {
if (!info->is_yuv) {
- if (drm_format_info_plane_cpp(info, 0) <= 2) {
+ if (image_format_info_plane_cpp(info, 0) <= 2) {
DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
return false;
}
--
git-series 0.9.1

2019-04-17 07:58:04

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 07/20] drm/fb: Move from drm_format_info to image_format_info

Start converting the DRM drivers by changing the struct drm_framebuffer
structure to hold a pointer to image_format_info instead, and converting
everyone that depends on it.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/Kconfig | 1 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 ++--
drivers/gpu/drm/arm/malidp_drv.c | 2 +-
drivers/gpu/drm/arm/malidp_planes.c | 8 ++++----
drivers/gpu/drm/armada/armada_fb.c | 2 +-
drivers/gpu/drm/armada/armada_overlay.c | 2 +-
drivers/gpu/drm/armada/armada_plane.c | 2 +-
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 2 +-
drivers/gpu/drm/bochs/bochs.h | 4 +++-
drivers/gpu/drm/bochs/bochs_hw.c | 2 +-
drivers/gpu/drm/drm_fb_cma_helper.c | 4 ++--
drivers/gpu/drm/drm_fb_helper.c | 14 +++++++-------
drivers/gpu/drm/drm_format_helper.c | 4 ++--
drivers/gpu/drm/drm_fourcc.c | 8 ++++----
drivers/gpu/drm/drm_framebuffer.c | 10 +++++-----
drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 ++--
drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +-
drivers/gpu/drm/gma500/framebuffer.c | 2 +-
drivers/gpu/drm/i915/i915_drv.h | 6 ++++--
drivers/gpu/drm/i915/intel_display.c | 10 +++++-----
drivers/gpu/drm/imx/ipuv3-plane.c | 4 ++--
drivers/gpu/drm/mediatek/mtk_drm_fb.c | 6 +++---
drivers/gpu/drm/meson/meson_overlay.c | 12 ++++++------
drivers/gpu/drm/msm/msm_fb.c | 10 +++++-----
drivers/gpu/drm/omapdrm/omap_fb.c | 6 +++---
drivers/gpu/drm/radeon/radeon_fb.c | 4 ++--
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 6 +++---
drivers/gpu/drm/stm/ltdc.c | 2 +-
drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +++---
drivers/gpu/drm/sun4i/sun4i_frontend.c | 18 +++++++++---------
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 ++--
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 ++++--
drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 5 +++--
drivers/gpu/drm/tegra/fb.c | 4 ++--
drivers/gpu/drm/zte/zx_plane.c | 2 +-
include/drm/drm_fourcc.h | 4 +++-
include/drm/drm_framebuffer.h | 4 ++--
include/drm/drm_mode_config.h | 5 +++--
38 files changed, 106 insertions(+), 95 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 39d5f7562f1c..a5bef1c83e7f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -12,6 +12,7 @@ menuconfig DRM
select FB_CMDLINE
select I2C
select I2C_ALGOBIT
+ select IMAGE_FORMATS
select DMA_SHARED_BUFFER
select SYNC_FILE
help
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 6edae6458be8..159b8d792102 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -121,7 +121,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
struct amdgpu_device *adev = rfbdev->adev;
struct drm_gem_object *gobj = NULL;
struct amdgpu_bo *abo = NULL;
@@ -133,7 +133,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
u32 cpp;

info = drm_get_format_info(adev->ddev, mode_cmd);
- cpp = drm_format_info_plane_cpp(info, 0);
+ cpp = image_format_info_plane_cpp(info, 0);

/* need to align pitch with crtc limits */
mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 21725c9b9f5e..9e5240c2d5c7 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -294,7 +294,7 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
int n_superblocks = 0;
- const struct drm_format_info *info;
+ const struct image_format_info *info;
struct drm_gem_object *objs = NULL;
u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
u32 afbc_superblock_width = 0, afbc_size = 0;
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 361c02988375..9874f98f2aa5 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -529,7 +529,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
for (i = 0; i < ms->n_planes; i++) {
u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);

- if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
+ if (((fb->pitches[i] * image_format_info_block_height(fb->format, i))
& (alignment - 1)) && !(fb->modifier)) {
DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
fb->pitches[i], i);
@@ -537,8 +537,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
}
}

- block_w = drm_format_info_block_width(fb->format, 0);
- block_h = drm_format_info_block_height(fb->format, 0);
+ block_w = image_format_info_block_width(fb->format, 0);
+ block_h = image_format_info_block_height(fb->format, 0);
if (fb->width % block_w || fb->height % block_h) {
DRM_DEBUG_KMS("Buffer width/height needs to be a multiple of tile sizes");
return -EINVAL;
@@ -633,7 +633,7 @@ static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
* in a tile.
*/
for (i = 0; i < num_strides; ++i) {
- unsigned int block_h = drm_format_info_block_height(mp->base.state->fb->format, i);
+ unsigned int block_h = image_format_info_block_height(mp->base.state->fb->format, i);

malidp_hw_write(mp->hwdev, pitches[i] * block_h,
mp->layer->base +
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index a2f6472eb482..10e9ab534658 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -87,7 +87,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
{
- const struct drm_format_info *info = drm_get_format_info(dev, mode);
+ const struct image_format_info *info = drm_get_format_info(dev, mode);
struct armada_gem_object *obj;
struct armada_framebuffer *dfb;
int ret;
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 8d770641fcc4..1acb026b2c6b 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -107,7 +107,7 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
if (old_state->src.x1 != state->src.x1 ||
old_state->src.y1 != state->src.y1 ||
old_state->fb != state->fb) {
- const struct drm_format_info *format;
+ const struct image_format_info *format;
u16 src_x, pitches[3];
u32 addrs[2][3];

diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 9f36423dd394..2e32fb2ccfb8 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -39,7 +39,7 @@ void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
u16 pitches[3], bool interlaced)
{
struct drm_framebuffer *fb = state->fb;
- const struct drm_format_info *format = fb->format;
+ const struct image_format_info *format = fb->format;
unsigned int num_planes = format->num_planes;
unsigned int x = state->src.x1 >> 16;
unsigned int y = state->src.y1 >> 16;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index fdd607ad27fe..abaa9ebe5f34 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -360,7 +360,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
{
unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
- const struct drm_format_info *format = state->base.fb->format;
+ const struct image_format_info *format = state->base.fb->format;

/*
* Rotation optimization is not working on RGB888 (rotation is still
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index 341cc9d1bab4..20b0a56af5ff 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -107,6 +107,8 @@ static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)

/* ---------------------------------------------------------------------- */

+struct image_format_info;
+
/* bochs_hw.c */
int bochs_hw_init(struct drm_device *dev);
void bochs_hw_fini(struct drm_device *dev);
@@ -114,7 +116,7 @@ void bochs_hw_fini(struct drm_device *dev);
void bochs_hw_setmode(struct bochs_device *bochs,
struct drm_display_mode *mode);
void bochs_hw_setformat(struct bochs_device *bochs,
- const struct drm_format_info *format);
+ const struct image_format_info *format);
void bochs_hw_setbase(struct bochs_device *bochs,
int x, int y, u64 addr);
int bochs_hw_load_edid(struct bochs_device *bochs);
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
index 3e04b2f0ec08..1ef1179fd6e8 100644
--- a/drivers/gpu/drm/bochs/bochs_hw.c
+++ b/drivers/gpu/drm/bochs/bochs_hw.c
@@ -234,7 +234,7 @@ void bochs_hw_setmode(struct bochs_device *bochs,
}

void bochs_hw_setformat(struct bochs_device *bochs,
- const struct drm_format_info *format)
+ const struct image_format_info *format)
{
DRM_DEBUG_DRIVER("format %c%c%c%c\n",
(format->format >> 0) & 0xff,
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 5f8074ffe7d9..52d1639faed1 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -74,8 +74,8 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
struct drm_gem_cma_object *obj;
dma_addr_t paddr;
u8 h_div = 1, v_div = 1;
- u32 block_w = drm_format_info_block_width(fb->format, plane);
- u32 block_h = drm_format_info_block_height(fb->format, plane);
+ u32 block_w = image_format_info_block_width(fb->format, plane);
+ u32 block_h = image_format_info_block_height(fb->format, plane);
u32 block_size = fb->format->char_per_block[plane];
u32 sample_x;
u32 sample_y;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 4fcbb9caaf68..c28060af95f0 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -767,7 +767,7 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip)
{
struct drm_framebuffer *fb = fb_helper->fb;
- unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
+ unsigned int cpp = image_format_info_plane_cpp(fb->format, 0);
size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
void *src = fb_helper->fbdev->screen_buffer + offset;
void *dst = fb_helper->buffer->vaddr + offset;
@@ -1698,8 +1698,8 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
var->pixclock = 0;
}

- if ((drm_format_info_block_width(fb->format, 0) > 1) ||
- (drm_format_info_block_height(fb->format, 0) > 1))
+ if ((image_format_info_block_width(fb->format, 0) > 1) ||
+ (image_format_info_block_height(fb->format, 0) > 1))
return -EINVAL;

/*
@@ -1932,9 +1932,9 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
DRM_DEBUG("test CRTC %d primary plane\n", i);

for (j = 0; j < plane->format_count; j++) {
- const struct drm_format_info *fmt;
+ const struct image_format_info *fmt;

- fmt = drm_format_info(plane->format_types[j]);
+ fmt = image_format_drm_lookup(plane->format_types[j]);

/*
* Do not consider YUV or other complicated formats
@@ -2055,8 +2055,8 @@ static void drm_fb_helper_fill_var(struct fb_info *info,
{
struct drm_framebuffer *fb = fb_helper->fb;

- WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) ||
- (drm_format_info_block_height(fb->format, 0) > 1));
+ WARN_ON((image_format_info_block_width(fb->format, 0) > 1) ||
+ (image_format_info_block_height(fb->format, 0) > 1));
info->pseudo_palette = fb_helper->pseudo_palette;
info->var.xres_virtual = fb->width;
info->var.yres_virtual = fb->height;
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index 14d85eb1989d..5b49526ab6fa 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -36,7 +36,7 @@ static unsigned int clip_offset(struct drm_rect *clip,
void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
struct drm_rect *clip)
{
- unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
+ unsigned int cpp = image_format_info_plane_cpp(fb->format, 0);
size_t len = (clip->x2 - clip->x1) * cpp;
unsigned int y, lines = clip->y2 - clip->y1;

@@ -63,7 +63,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
struct drm_framebuffer *fb,
struct drm_rect *clip)
{
- unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
+ unsigned int cpp = image_format_info_plane_cpp(fb->format, 0);
unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);
size_t len = (clip->x2 - clip->x1) * cpp;
unsigned int y, lines = clip->y2 - clip->y1;
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 35b459d186c5..6537f4906c50 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -313,20 +313,20 @@ EXPORT_SYMBOL(drm_format_info);
* @mode_cmd: metadata from the userspace fb creation request
*
* Returns:
- * The instance of struct drm_format_info that describes the pixel format, or
+ * The instance of struct image_format_info that describes the pixel format, or
* NULL if the format is unsupported.
*/
-const struct drm_format_info *
+const struct image_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;
+ const struct image_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);
+ info = image_format_drm_lookup(mode_cmd->pixel_format);

return info;
}
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index d8d75e25f6fb..db7aee1fc8fd 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -146,7 +146,7 @@ int drm_mode_addfb_ioctl(struct drm_device *dev,
}

static int fb_plane_width(int width,
- const struct drm_format_info *format, int plane)
+ const struct image_format_info *format, int plane)
{
if (plane == 0)
return width;
@@ -155,7 +155,7 @@ static int fb_plane_width(int width,
}

static int fb_plane_height(int height,
- const struct drm_format_info *format, int plane)
+ const struct image_format_info *format, int plane)
{
if (plane == 0)
return height;
@@ -166,11 +166,11 @@ static int fb_plane_height(int height,
static int framebuffer_check(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *r)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
int i;

/* check if the format is supported at all */
- info = __drm_format_info(r->pixel_format);
+ info = __image_format_drm_lookup(r->pixel_format);
if (!info) {
struct drm_format_name_buf format_name;

@@ -197,7 +197,7 @@ static int framebuffer_check(struct drm_device *dev,
unsigned int width = fb_plane_width(r->width, info, i);
unsigned int height = fb_plane_height(r->height, info, i);
unsigned int block_size = info->char_per_block[i];
- u64 min_pitch = drm_format_info_min_pitch(info, i, width);
+ u64 min_pitch = image_format_info_min_pitch(info, i, width);

if (!block_size && (r->modifier[i] == DRM_FORMAT_MOD_LINEAR)) {
DRM_DEBUG_KMS("Format requires non-linear modifier for plane %d\n", i);
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 65edb1ccb185..b54a12dd6712 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -149,7 +149,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
const struct drm_mode_fb_cmd2 *mode_cmd,
const struct drm_framebuffer_funcs *funcs)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
struct drm_gem_object *objs[4];
struct drm_framebuffer *fb;
int ret, i;
@@ -171,7 +171,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
}

min_size = (height - 1) * mode_cmd->pitches[i]
- + drm_format_info_min_pitch(info, i, width)
+ + image_format_info_min_pitch(info, i, width)
+ mode_cmd->offsets[i];

if (objs[i]->size < min_size) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 1f11ab0f8e9d..713b3e07d7f2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -98,7 +98,7 @@ static struct drm_framebuffer *
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
- const struct drm_format_info *info = drm_get_format_info(dev, mode_cmd);
+ const struct image_format_info *info = drm_get_format_info(dev, mode_cmd);
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
struct drm_framebuffer *fb;
int i;
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 1794ab90b2cc..562c250b9e7e 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -225,7 +225,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
int ret;

/*
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 35d0782c077e..6040ec11d643 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -376,6 +376,8 @@ enum i915_cache_level {

#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */

+struct image_format_info;
+
struct intel_fbc {
/* This is always the inner lock when overlapping with struct_mutex and
* it's the outer lock when overlapping with stolen_lock. */
@@ -432,7 +434,7 @@ struct intel_fbc {
} plane;

struct {
- const struct drm_format_info *format;
+ const struct image_format_info *format;
unsigned int stride;
} fb;
} state_cache;
@@ -455,7 +457,7 @@ struct intel_fbc {
} crtc;

struct {
- const struct drm_format_info *format;
+ const struct image_format_info *format;
unsigned int stride;
} fb;

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3bd40a4a6739..6a0c4f505593 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2431,15 +2431,15 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
* us a ratio of one byte in the CCS for each 8x16 pixels in the
* main surface.
*/
-static const struct drm_format_info ccs_formats[] = {
+static const struct image_format_info ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
};

-static const struct drm_format_info *
-lookup_format_info(const struct drm_format_info formats[],
+static const struct image_format_info *
+lookup_format_info(const struct image_format_info formats[],
int num_formats, u32 format)
{
int i;
@@ -2452,7 +2452,7 @@ lookup_format_info(const struct drm_format_info formats[],
return NULL;
}

-static const struct drm_format_info *
+static const struct image_format_info *
intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
{
switch (cmd->modifier[0]) {
@@ -5019,7 +5019,7 @@ static int
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
unsigned int scaler_user, int *scaler_id,
int src_w, int src_h, int dst_w, int dst_h,
- const struct drm_format_info *format, bool need_scaler)
+ const struct image_format_info *format, bool need_scaler)
{
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 4a54a5c192d2..f1e399085288 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -553,7 +553,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
unsigned long alpha_eba = 0;
enum ipu_color_space ics;
unsigned int axi_id = 0;
- const struct drm_format_info *info;
+ const struct image_format_info *info;
u8 burstsize, num_bursts;
u32 width, height;
int active;
@@ -627,7 +627,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,

width = drm_rect_width(&state->src) >> 16;
height = drm_rect_height(&state->src) >> 16;
- info = drm_format_info(fb->format->format);
+ info = fb->format;
ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
&burstsize, &num_bursts);

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
index 0d5334a5a9a7..6b40bbb1e2ba 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
@@ -32,7 +32,7 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode,
struct drm_gem_object *obj)
{
- const struct drm_format_info *info = drm_get_format_info(dev, mode);
+ const struct image_format_info *info = drm_get_format_info(dev, mode);
struct drm_framebuffer *fb;
int ret;

@@ -89,7 +89,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *cmd)
{
- const struct drm_format_info *info = drm_get_format_info(dev, cmd);
+ const struct image_format_info *info = drm_get_format_info(dev, cmd);
struct drm_framebuffer *fb;
struct drm_gem_object *gem;
unsigned int width = cmd->width;
@@ -104,7 +104,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
if (!gem)
return ERR_PTR(-ENOENT);

- bpp = drm_format_info_plane_cpp(info, 0);
+ bpp = image_format_info_plane_cpp(info, 0);
size = (height - 1) * cmd->pitches[0] + width * bpp;
size += cmd->offsets[0];

diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index 55b3f2f2e608..3a0aee9367e0 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -466,8 +466,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2];
priv->viu.vd1_stride2 = fb->pitches[2];
priv->viu.vd1_height2 =
- drm_format_info_plane_height(fb->format,
- fb->height, 2);
+ image_format_info_plane_height(fb->format,
+ fb->height, 2);
DRM_DEBUG("plane 2 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr2,
priv->viu.vd1_stride2,
@@ -478,8 +478,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1];
priv->viu.vd1_stride1 = fb->pitches[1];
priv->viu.vd1_height1 =
- drm_format_info_plane_height(fb->format,
- fb->height, 1);
+ image_format_info_plane_height(fb->format,
+ fb->height, 1);
DRM_DEBUG("plane 1 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr1,
priv->viu.vd1_stride1,
@@ -490,8 +490,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0];
priv->viu.vd1_stride0 = fb->pitches[0];
priv->viu.vd1_height0 =
- drm_format_info_plane_height(fb->format,
- fb->height, 0);
+ image_format_info_plane_height(fb->format,
+ fb->height, 0);
DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n",
priv->viu.vd1_addr0,
priv->viu.vd1_stride0,
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 29e45f2144b5..68bf59d797db 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -106,8 +106,8 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb)
struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
- const struct drm_format_info *info = drm_get_format_info(dev,
- mode_cmd);
+ const struct image_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct drm_gem_object *bos[4] = {0};
struct drm_framebuffer *fb;
int ret, i, n = info->num_planes;
@@ -137,8 +137,8 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
- const struct drm_format_info *info = drm_get_format_info(dev,
- mode_cmd);
+ const struct image_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_framebuffer *msm_fb = NULL;
@@ -181,7 +181,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
unsigned int min_size;

min_size = (height - 1) * mode_cmd->pitches[i]
- + width * drm_format_info_plane_cpp(info, i)
+ + width * image_format_info_plane_cpp(info, i)
+ mode_cmd->offsets[i];

if (bos[i]->size < min_size) {
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 6557b2d6e16e..1d4143adf829 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -298,8 +298,8 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
- const struct drm_format_info *info = drm_get_format_info(dev,
- mode_cmd);
+ const struct image_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
unsigned int num_planes = info->num_planes;
struct drm_gem_object *bos[4];
struct drm_framebuffer *fb;
@@ -329,7 +329,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
- const struct drm_format_info *format = NULL;
+ const struct image_format_info *format = NULL;
struct omap_framebuffer *omap_fb = NULL;
struct drm_framebuffer *fb = NULL;
unsigned int pitch = mode_cmd->pitches[0];
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index dbf596fc4339..2c23c2311b1b 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -125,7 +125,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
- const struct drm_format_info *info;
+ const struct image_format_info *info;
struct radeon_device *rdev = rfbdev->rdev;
struct drm_gem_object *gobj = NULL;
struct radeon_bo *rbo = NULL;
@@ -137,7 +137,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
u32 cpp;

info = drm_get_format_info(rdev->ddev, mode_cmd);
- cpp = drm_format_info_plane_cpp(info, 0);
+ cpp = image_format_info_plane_cpp(info, 0);

/* need to align pitch with crtc limits */
mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 57873c99ae29..69b64ba9dcfa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -74,8 +74,8 @@ static struct drm_framebuffer *
rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
- const struct drm_format_info *info = drm_get_format_info(dev,
- mode_cmd);
+ const struct image_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct drm_framebuffer *fb;
struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
struct drm_gem_object *obj;
@@ -98,7 +98,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,

min_size = (height - 1) * mode_cmd->pitches[i] +
mode_cmd->offsets[i] +
- width * drm_format_info_plane_cpp(info, i);
+ width * image_format_info_plane_cpp(info, i);

if (obj->size < min_size) {
drm_gem_object_put_unlocked(obj);
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 6bb3cd3a1a01..30efc822b2ce 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -779,7 +779,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,

/* Configures the color frame buffer pitch in bytes & line length */
pitch_in_bytes = fb->pitches[0];
- line_length = drm_format_info_plane_cpp(fb->format, 0) *
+ line_length = image_format_info_plane_cpp(fb->format, 0) *
(x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
val = ((pitch_in_bytes << 16) | line_length);
reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 4e5922c89d7b..92766f8995d9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -203,7 +203,7 @@ static int sun4i_backend_update_yuv_format(struct sun4i_backend *backend,
{
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
- const struct drm_format_info *format = fb->format;
+ const struct image_format_info *format = fb->format;
const uint32_t fmt = format->format;
u32 val = SUN4I_BACKEND_IYUVCTL_EN;
int i;
@@ -222,8 +222,8 @@ static int sun4i_backend_update_yuv_format(struct sun4i_backend *backend,
SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN);

/* TODO: Add support for the multi-planar YUV formats */
- if (drm_format_info_is_yuv_packed(format) &&
- drm_format_info_is_yuv_sampling_422(format))
+ if (image_format_info_is_yuv_packed(format) &&
+ image_format_info_is_yuv_sampling_422(format))
val |= SUN4I_BACKEND_IYUVCTL_FBFMT_PACKED_YUV422;
else
DRM_DEBUG_DRIVER("Unsupported YUV format (0x%x)\n", fmt);
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index 346c8071bd38..75c2f9886768 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -241,18 +241,18 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
EXPORT_SYMBOL(sun4i_frontend_update_buffer);

static int
-sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format,
+sun4i_frontend_drm_format_to_input_fmt(const struct image_format_info *format,
u32 *val)
{
if (!format->is_yuv)
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
- else if (drm_format_info_is_yuv_sampling_411(format))
+ else if (image_format_info_is_yuv_sampling_411(format))
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV411;
- else if (drm_format_info_is_yuv_sampling_420(format))
+ else if (image_format_info_is_yuv_sampling_420(format))
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420;
- else if (drm_format_info_is_yuv_sampling_422(format))
+ else if (image_format_info_is_yuv_sampling_422(format))
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422;
- else if (drm_format_info_is_yuv_sampling_444(format))
+ else if (image_format_info_is_yuv_sampling_444(format))
*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV444;
else
return -EINVAL;
@@ -261,7 +261,7 @@ sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format,
}

static int
-sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format,
+sun4i_frontend_drm_format_to_input_mode(const struct image_format_info *format,
uint64_t modifier, u32 *val)
{
bool tiled = (modifier == DRM_FORMAT_MOD_ALLWINNER_TILED);
@@ -287,11 +287,11 @@ sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format,
}

static int
-sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format,
+sun4i_frontend_drm_format_to_input_sequence(const struct image_format_info *format,
u32 *val)
{
/* Planar formats have an explicit input sequence. */
- if (drm_format_info_is_yuv_planar(format)) {
+ if (image_format_info_is_yuv_planar(format)) {
*val = 0;
return 0;
}
@@ -401,7 +401,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
{
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
- const struct drm_format_info *format = fb->format;
+ const struct image_format_info *format = fb->format;
uint64_t modifier = fb->modifier;
u32 out_fmt_val;
u32 in_fmt_val, in_mod_val, in_ps_val;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index bb8e026d6405..2f64c056d68d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -75,7 +75,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
unsigned int zpos)
{
struct drm_plane_state *state = plane->state;
- const struct drm_format_info *format = state->fb->format;
+ const struct image_format_info *format = state->fb->format;
u32 src_w, src_h, dst_w, dst_h;
u32 bld_base, ch_base;
u32 outsize, insize;
@@ -267,7 +267,7 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
{
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
- const struct drm_format_info *format = fb->format;
+ const struct image_format_info *format = fb->format;
struct drm_gem_cma_object *gem;
u32 dx, dy, src_x, src_y;
dma_addr_t paddr;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
index 7ba75011adf9..1d22331af5fe 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
@@ -9,6 +9,8 @@
* warranty of any kind, whether express or implied.
*/

+#include <linux/image-formats.h>
+
#include "sun8i_vi_scaler.h"

static const u32 lan3coefftab32_left[480] = {
@@ -869,7 +871,7 @@ static int sun8i_vi_scaler_coef_index(unsigned int step)

static void sun8i_vi_scaler_set_coeff(struct regmap *map, u32 base,
u32 hstep, u32 vstep,
- const struct drm_format_info *format)
+ const struct image_format_info *format)
{
const u32 *ch_left, *ch_right, *cy;
int offset, i;
@@ -926,7 +928,7 @@ void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
u32 hscale, u32 vscale, u32 hphase, u32 vphase,
- const struct drm_format_info *format)
+ const struct image_format_info *format)
{
u32 chphase, cvphase;
u32 insize, outsize;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
index 68f6593b369a..878a689e532a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
@@ -9,7 +9,6 @@
#ifndef _SUN8I_VI_SCALER_H_
#define _SUN8I_VI_SCALER_H_

-#include <drm/drm_fourcc.h>
#include "sun8i_mixer.h"

#define DE2_VI_SCALER_UNIT_BASE 0x20000
@@ -69,10 +68,12 @@
#define SUN50I_SCALER_VSU_ANGLE_SHIFT(x) (((x) << 16) & 0xF)
#define SUN50I_SCALER_VSU_ANGLE_OFFSET(x) ((x) & 0xFF)

+struct image_format_info;
+
void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable);
void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
u32 hscale, u32 vscale, u32 hphase, u32 vphase,
- const struct drm_format_info *format);
+ const struct image_format_info *format);

#endif
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index d1042196a30f..5b99741704fc 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -131,7 +131,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *cmd)
{
- const struct drm_format_info *info = drm_get_format_info(drm, cmd);
+ const struct image_format_info *info = drm_get_format_info(drm, cmd);
struct tegra_bo *planes[4];
struct drm_gem_object *gem;
struct drm_framebuffer *fb;
@@ -149,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
goto unreference;
}

- bpp = drm_format_info_plane_cpp(info, i);
+ bpp = image_format_info_plane_cpp(info, i);

size = (height - 1) * cmd->pitches[i] +
width * bpp + cmd->offsets[i];
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index d97a4dff515d..7895ba52709a 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -222,7 +222,7 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane,
cma_obj = drm_fb_cma_get_gem_obj(fb, i);
paddr = cma_obj->paddr + fb->offsets[i];
paddr += src_y * fb->pitches[i];
- paddr += src_x * drm_format_info_plane_cpp(fb->format, i);
+ paddr += src_x * image_format_info_plane_cpp(fb->format, i);
zx_writel(paddr_reg, paddr);
paddr_reg += 4;
}
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 4ef8ccb5d236..38f152b5da08 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -49,6 +49,7 @@

struct drm_device;
struct drm_mode_fb_cmd2;
+struct image_format_info;

/**
* struct drm_format_info - information about a DRM format
@@ -323,7 +324,8 @@ int drm_format_info_plane_height(const struct drm_format_info *info, int height,

const struct drm_format_info *__drm_format_info(u32 format);
const struct drm_format_info *drm_format_info(u32 format);
-const struct drm_format_info *
+
+const struct image_format_info *
drm_get_format_info(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd);
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index c23016748e3f..dc7dc48c8580 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -24,6 +24,7 @@
#define __DRM_FRAMEBUFFER_H__

#include <linux/ctype.h>
+#include <linux/image-formats.h>
#include <linux/list.h>
#include <linux/sched.h>

@@ -32,7 +33,6 @@
struct drm_clip_rect;
struct drm_device;
struct drm_file;
-struct drm_format_info;
struct drm_framebuffer;
struct drm_gem_object;

@@ -135,7 +135,7 @@ struct drm_framebuffer {
/**
* @format: framebuffer format information
*/
- const struct drm_format_info *format;
+ const struct image_format_info *format;
/**
* @funcs: framebuffer vfunc table
*/
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 7f60e8eb269a..717fb536078b 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -35,9 +35,10 @@ struct drm_file;
struct drm_device;
struct drm_atomic_state;
struct drm_mode_fb_cmd2;
-struct drm_format_info;
struct drm_display_mode;

+struct image_format_info;
+
/**
* struct drm_mode_config_funcs - basic driver provided mode setting functions
*
@@ -89,7 +90,7 @@ struct drm_mode_config_funcs {
* The format information specific to the given fb metadata, or
* NULL if none is found.
*/
- const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);
+ const struct image_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);

/**
* @output_poll_changed:
--
git-series 0.9.1

2019-04-17 07:58:06

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 09/20] drm/client: Convert to generic image format library

Now that we have a generic image format libary, let's convert the rest of
the DRM core to use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/drm_client.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 169d8eeaa662..89e1f7bc5a30 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -243,7 +243,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
static struct drm_client_buffer *
drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
{
- const struct drm_format_info *info = drm_format_info(format);
+ const struct image_format_info *info = image_format_drm_lookup(format);
struct drm_mode_create_dumb dumb_args = { };
struct drm_device *dev = client->dev;
struct drm_client_buffer *buffer;
@@ -259,7 +259,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u

dumb_args.width = width;
dumb_args.height = height;
- dumb_args.bpp = drm_format_info_plane_cpp(info, 0) * 8;
+ dumb_args.bpp = image_format_info_plane_cpp(info, 0) * 8;
ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
if (ret)
goto err_delete;
@@ -319,10 +319,10 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
{
struct drm_client_dev *client = buffer->client;
struct drm_mode_fb_cmd fb_req = { };
- const struct drm_format_info *info;
+ const struct image_format_info *info;
int ret;

- info = drm_format_info(format);
+ info = image_format_drm_lookup(format);
fb_req.bpp = info->cpp[0] * 8;
fb_req.depth = info->depth;
fb_req.width = width;
--
git-series 0.9.1

2019-04-17 07:58:32

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 18/20] lib: image-formats: Add v4l2 formats support

V4L2 uses different fourcc's than DRM, and has a different set of formats.
For now, let's add the v4l2 fourcc's for the already existing formats.

Signed-off-by: Maxime Ripard <[email protected]>
---
include/linux/image-formats.h | 9 +++++-
lib/image-formats.c | 62 ++++++++++++++++++++++++++++++++++++-
2 files changed, 71 insertions(+)

diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
index ec43d9f9a527..b78b8e861fc9 100644
--- a/include/linux/image-formats.h
+++ b/include/linux/image-formats.h
@@ -50,6 +50,13 @@ struct image_format_info {
};

/**
+ * @v4l2_fmt:
+ *
+ * V4L2 4CC format identifier (V4L2_PIX_FMT_*)
+ */
+ u32 v4l2_fmt;
+
+ /**
* @depth:
*
* Color depth (number of bits per pixel excluding padding bits),
@@ -382,6 +389,8 @@ uint64_t image_format_info_min_pitch(const struct image_format_info *info,
}

const struct image_format_info *__image_format_drm_lookup(u32 drm);
+const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2);
const struct image_format_info *image_format_drm_lookup(u32 drm);
+const struct image_format_info *image_format_v4l2_lookup(u32 v4l2);

#endif /* _IMAGE_FORMATS_H_ */
diff --git a/lib/image-formats.c b/lib/image-formats.c
index 1e52a7410222..25fa22d243fb 100644
--- a/lib/image-formats.c
+++ b/lib/image-formats.c
@@ -25,12 +25,14 @@
#include <linux/image-formats.h>
#include <linux/kernel.h>
#include <linux/math64.h>
+#include <linux/videodev2.h>

#include <uapi/drm/drm_fourcc.h>

static const struct image_format_info formats[] = {
{
.drm_fmt = DRM_FORMAT_C8,
+ .v4l2_fmt = V4L2_PIX_FMT_GREY,
.depth = 8,
.num_planes = 1,
.cpp = { 1, 0, 0 },
@@ -38,6 +40,7 @@ static const struct image_format_info formats[] = {
.vsub = 1,
}, {
.drm_fmt = DRM_FORMAT_RGB332,
+ .v4l2_fmt = V4L2_PIX_FMT_RGB332,
.depth = 8,
.num_planes = 1,
.cpp = { 1, 0, 0 },
@@ -172,6 +175,7 @@ static const struct image_format_info formats[] = {
.has_alpha = true,
}, {
.drm_fmt = DRM_FORMAT_RGB565,
+ .v4l2_fmt = V4L2_PIX_FMT_RGB565X,
.depth = 16,
.num_planes = 1,
.cpp = { 2, 0, 0 },
@@ -186,6 +190,7 @@ static const struct image_format_info formats[] = {
.vsub = 1,
}, {
.drm_fmt = DRM_FORMAT_RGB888,
+ .v4l2_fmt = V4L2_PIX_FMT_BGR24,
.depth = 24,
.num_planes = 1,
.cpp = { 3, 0, 0 },
@@ -193,6 +198,7 @@ static const struct image_format_info formats[] = {
.vsub = 1,
}, {
.drm_fmt = DRM_FORMAT_BGR888,
+ .v4l2_fmt = V4L2_PIX_FMT_RGB24,
.depth = 24,
.num_planes = 1,
.cpp = { 3, 0, 0 },
@@ -200,6 +206,7 @@ static const struct image_format_info formats[] = {
.vsub = 1,
}, {
.drm_fmt = DRM_FORMAT_XRGB8888,
+ .v4l2_fmt = V4L2_PIX_FMT_XBGR32,
.depth = 24,
.num_planes = 1,
.cpp = { 4, 0, 0 },
@@ -304,6 +311,7 @@ static const struct image_format_info formats[] = {
.has_alpha = true,
}, {
.drm_fmt = DRM_FORMAT_ARGB8888,
+ .v4l2_fmt = V4L2_PIX_FMT_ABGR32,
.depth = 32,
.num_planes = 1,
.cpp = { 4, 0, 0 },
@@ -384,6 +392,7 @@ static const struct image_format_info formats[] = {
.has_alpha = true,
}, {
.drm_fmt = DRM_FORMAT_YUV410,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV410,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -392,6 +401,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YVU410,
+ .v4l2_fmt = V4L2_PIX_FMT_YVU410,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -416,6 +426,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YUV420,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV420,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -424,6 +435,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YVU420,
+ .v4l2_fmt = V4L2_PIX_FMT_YVU420,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -432,6 +444,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YUV422,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -448,6 +461,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YUV444,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV444,
.depth = 0,
.num_planes = 3,
.cpp = { 1, 1, 1 },
@@ -464,6 +478,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV12,
+ .v4l2_fmt = V4L2_PIX_FMT_NV12,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -472,6 +487,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV21,
+ .v4l2_fmt = V4L2_PIX_FMT_NV21,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -480,6 +496,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV16,
+ .v4l2_fmt = V4L2_PIX_FMT_NV16,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -488,6 +505,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV61,
+ .v4l2_fmt = V4L2_PIX_FMT_NV61,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -496,6 +514,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV24,
+ .v4l2_fmt = V4L2_PIX_FMT_NV24,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -504,6 +523,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_NV42,
+ .v4l2_fmt = V4L2_PIX_FMT_NV42,
.depth = 0,
.num_planes = 2,
.cpp = { 1, 2, 0 },
@@ -512,6 +532,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YUYV,
+ .v4l2_fmt = V4L2_PIX_FMT_YUYV,
.depth = 0,
.num_planes = 1,
.cpp = { 2, 0, 0 },
@@ -520,6 +541,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_YVYU,
+ .v4l2_fmt = V4L2_PIX_FMT_YVYU,
.depth = 0,
.num_planes = 1,
.cpp = { 2, 0, 0 },
@@ -528,6 +550,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_UYVY,
+ .v4l2_fmt = V4L2_PIX_FMT_UYVY,
.depth = 0,
.num_planes = 1,
.cpp = { 2, 0, 0 },
@@ -536,6 +559,7 @@ static const struct image_format_info formats[] = {
.is_yuv = true,
}, {
.drm_fmt = DRM_FORMAT_VYUY,
+ .v4l2_fmt = V4L2_PIX_FMT_VYUY,
.depth = 0,
.num_planes = 1,
.cpp = { 2, 0, 0 },
@@ -653,3 +677,41 @@ const struct image_format_info *image_format_drm_lookup(u32 drm)
return format;
}
EXPORT_SYMBOL(image_format_drm_lookup);
+
+/**
+ * __image_format_v4l2_lookup - query information for a given format
+ * @v4l2: V4L2 fourcc pixel format (V4L2_PIX_FMT_*)
+ *
+ * The caller should only pass a supported pixel format to this function.
+ *
+ * Returns:
+ * The instance of struct image_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
+ */
+const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2)
+{
+ return __image_format_lookup(v4l2_fmt, v4l2);
+}
+EXPORT_SYMBOL(__image_format_v4l2_lookup);
+
+/**
+ * image_format_v4l2_lookup - query information for a given format
+ * @v4l2: V4L2 fourcc pixel format (V4L2_PIX_FMT_*)
+ *
+ * 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 image_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
+ */
+const struct image_format_info *image_format_v4l2_lookup(u32 v4l2)
+{
+ const struct image_format_info *format;
+
+ format = __image_format_v4l2_lookup(v4l2);
+
+ WARN_ON(!format);
+ return format;
+}
+EXPORT_SYMBOL(image_format_v4l2_lookup);
--
git-series 0.9.1

2019-04-17 07:59:39

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 16/20] drm/tegra: Convert to generic image format library

Now that we have a generic image format libary, let's convert drivers to
use it so that we can deprecate the old DRM one.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/tegra/plane.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index d068e8aa3553..e1d82cbdabe8 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -6,6 +6,8 @@
* published by the Free Software Foundation.
*/

+#include <linux/image-formats.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
@@ -76,7 +78,7 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
{
- const struct drm_format_info *info = drm_format_info(format);
+ const struct image_format_info *info = image_format_drm_lookup(format);

if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
--
git-series 0.9.1

2019-04-17 07:59:58

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 03/20] drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp

So far, the drm_format_plane_cpp function was operating on the format's
fourcc and was doing a lookup to retrieve the drm_format_info structure and
return the cpp.

However, this is inefficient since in most cases, we will have the
drm_format_info pointer already available so we shouldn't have to perform a
new lookup. Some drm_fourcc functions also already operate on the
drm_format_info pointer for that reason, so the API is quite inconsistent
there.

Let's follow the latter pattern and remove the extra lookup while being a
bit more consistent. In order to be extra consistent, also rename that
function to drm_format_info_plane_cpp and to a static function in the
header to match the current policy.

Reviewed-by: Emil Velikov <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +++-
drivers/gpu/drm/arm/malidp_hw.c | 3 ++-
drivers/gpu/drm/arm/malidp_planes.c | 2 +-
drivers/gpu/drm/drm_client.c | 3 ++-
drivers/gpu/drm/drm_fb_helper.c | 2 +-
drivers/gpu/drm/drm_format_helper.c | 4 ++--
drivers/gpu/drm/drm_fourcc.c | 20 --------------------
drivers/gpu/drm/i915/intel_sprite.c | 3 ++-
drivers/gpu/drm/mediatek/mtk_drm_fb.c | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 3 ++-
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +-
drivers/gpu/drm/msm/msm_fb.c | 2 +-
drivers/gpu/drm/radeon/radeon_fb.c | 4 +++-
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +-
drivers/gpu/drm/stm/ltdc.c | 2 +-
drivers/gpu/drm/tegra/fb.c | 2 +-
drivers/gpu/drm/zte/zx_plane.c | 2 +-
include/drm/drm_fourcc.h | 18 +++++++++++++++++-
18 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index e47609218839..06e73a343724 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -121,6 +121,8 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
+ const struct drm_format_info *info = drm_get_format_info(dev,
+ mode_cmd);
struct amdgpu_device *adev = rfbdev->adev;
struct drm_gem_object *gobj = NULL;
struct amdgpu_bo *abo = NULL;
@@ -131,7 +133,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
int height = mode_cmd->height;
u32 cpp;

- cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
+ cpp = drm_format_info_plane_cpp(info, 0);

/* need to align pitch with crtc limits */
mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 8df12e9a33bb..1c9e869f4c52 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -382,7 +382,8 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *

int malidp_format_get_bpp(u32 fmt)
{
- int bpp = drm_format_plane_cpp(fmt, 0) * 8;
+ const struct drm_format_info *info = drm_format_info(fmt);
+ int bpp = drm_format_info_plane_cpp(info, 0) * 8;

if (bpp == 0) {
switch (fmt) {
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 8f89813d08c1..361c02988375 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -227,7 +227,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,

if (modifier & AFBC_SPLIT) {
if (!info->is_yuv) {
- if (drm_format_plane_cpp(format, 0) <= 2) {
+ if (drm_format_info_plane_cpp(info, 0) <= 2) {
DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
return false;
}
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index f20d1dda3961..169d8eeaa662 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -243,6 +243,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
static struct drm_client_buffer *
drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
{
+ const struct drm_format_info *info = drm_format_info(format);
struct drm_mode_create_dumb dumb_args = { };
struct drm_device *dev = client->dev;
struct drm_client_buffer *buffer;
@@ -258,7 +259,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u

dumb_args.width = width;
dumb_args.height = height;
- dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
+ dumb_args.bpp = drm_format_info_plane_cpp(info, 0) * 8;
ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
if (ret)
goto err_delete;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 4de4b9d59d49..4fcbb9caaf68 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -767,7 +767,7 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip)
{
struct drm_framebuffer *fb = fb_helper->fb;
- unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
+ unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
void *src = fb_helper->fbdev->screen_buffer + offset;
void *dst = fb_helper->buffer->vaddr + offset;
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index da388012df2a..14d85eb1989d 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -36,7 +36,7 @@ static unsigned int clip_offset(struct drm_rect *clip,
void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
struct drm_rect *clip)
{
- unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
+ unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
size_t len = (clip->x2 - clip->x1) * cpp;
unsigned int y, lines = clip->y2 - clip->y1;

@@ -63,7 +63,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
struct drm_framebuffer *fb,
struct drm_rect *clip)
{
- unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
+ unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0);
unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);
size_t len = (clip->x2 - clip->x1) * cpp;
unsigned int y, lines = clip->y2 - clip->y1;
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index e4a2c8372c8b..5f63fc74e265 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -333,26 +333,6 @@ drm_get_format_info(struct drm_device *dev,
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
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 2913e89280d7..e35601b1f878 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -325,7 +325,8 @@ skl_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
- int cpp = drm_format_plane_cpp(pixel_format, 0);
+ const struct drm_format_info *info = drm_format_info(pixel_format);
+ int cpp = drm_format_info_plane_cpp(info, 0);

/*
* "The stride in bytes must not exceed the
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
index 68fdef8b12bd..0d5334a5a9a7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
@@ -104,7 +104,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
if (!gem)
return ERR_PTR(-ENOENT);

- bpp = drm_format_plane_cpp(cmd->pixel_format, 0);
+ bpp = drm_format_info_plane_cpp(info, 0);
size = (height - 1) * cmd->pitches[0] + width * bpp;
size += cmd->offsets[0];

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index b0cf63c4e3d7..a565dccaba3a 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -782,6 +782,7 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)

static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
{
+ const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ARGB8888);
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
@@ -800,7 +801,7 @@ static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
width = mdp5_crtc->cursor.width;
height = mdp5_crtc->cursor.height;

- stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
+ stride = width * drm_format_info_plane_cpp(info, 0);

get_roi(crtc, &roi_w, &roi_h);

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index b30b2f4efc60..1ca294694597 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -158,7 +158,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
for (i = 0; i < nplanes; i++) {
int n, fetch_stride, cpp;

- cpp = drm_format_plane_cpp(fmt, i);
+ cpp = drm_format_info_plane_cpp(info, i);
fetch_stride = width * cpp / (i ? hsub : 1);

n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index f69c0afd6ec6..29e45f2144b5 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -181,7 +181,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
unsigned int min_size;

min_size = (height - 1) * mode_cmd->pitches[i]
- + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)
+ + width * drm_format_info_plane_cpp(info, i)
+ mode_cmd->offsets[i];

if (bos[i]->size < min_size) {
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 1298b84cb1c7..dbf596fc4339 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -125,6 +125,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
+ const struct drm_format_info *info;
struct radeon_device *rdev = rfbdev->rdev;
struct drm_gem_object *gobj = NULL;
struct radeon_bo *rbo = NULL;
@@ -135,7 +136,8 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
int height = mode_cmd->height;
u32 cpp;

- cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
+ info = drm_get_format_info(rdev->ddev, mode_cmd);
+ cpp = drm_format_info_plane_cpp(info, 0);

/* need to align pitch with crtc limits */
mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index c318fae28581..57873c99ae29 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -98,7 +98,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,

min_size = (height - 1) * mode_cmd->pitches[i] +
mode_cmd->offsets[i] +
- width * drm_format_plane_cpp(mode_cmd->pixel_format, i);
+ width * drm_format_info_plane_cpp(info, i);

if (obj->size < min_size) {
drm_gem_object_put_unlocked(obj);
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 32fd6a3b37fb..6bb3cd3a1a01 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -779,7 +779,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,

/* Configures the color frame buffer pitch in bytes & line length */
pitch_in_bytes = fb->pitches[0];
- line_length = drm_format_plane_cpp(fb->format->format, 0) *
+ line_length = drm_format_info_plane_cpp(fb->format, 0) *
(x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
val = ((pitch_in_bytes << 16) | line_length);
reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 94fb75089d87..d1042196a30f 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -149,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
goto unreference;
}

- bpp = drm_format_plane_cpp(cmd->pixel_format, i);
+ bpp = drm_format_info_plane_cpp(info, i);

size = (height - 1) * cmd->pitches[i] +
width * bpp + cmd->offsets[i];
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index c6a8be444300..d97a4dff515d 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -222,7 +222,7 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane,
cma_obj = drm_fb_cma_get_gem_obj(fb, i);
paddr = cma_obj->paddr + fb->offsets[i];
paddr += src_y * fb->pitches[i];
- paddr += src_x * drm_format_plane_cpp(format, i);
+ paddr += src_x * drm_format_info_plane_cpp(fb->format, i);
zx_writel(paddr_reg, paddr);
paddr_reg += 4;
}
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index eeec449d6c6a..6b5a82b31bc4 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -260,6 +260,23 @@ drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info)
return info->is_yuv && info->hsub == 1 && info->vsub == 1;
}

+/**
+ * drm_format_info_plane_cpp - determine the bytes per pixel value
+ * @format: pixel format info
+ * @plane: plane index
+ *
+ * Returns:
+ * The bytes per pixel value for the specified plane.
+ */
+static inline
+int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ return info->cpp[plane];
+}
+
const struct drm_format_info *__drm_format_info(u32 format);
const struct drm_format_info *drm_format_info(u32 format);
const struct drm_format_info *
@@ -268,7 +285,6 @@ drm_get_format_info(struct drm_device *dev,
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
uint32_t bpp, uint32_t depth);
-int drm_format_plane_cpp(uint32_t format, int plane);
int drm_format_plane_width(int width, uint32_t format, int plane);
int drm_format_plane_height(int height, uint32_t format, int plane);
unsigned int drm_format_info_block_width(const struct drm_format_info *info,
--
git-series 0.9.1

2019-04-17 11:04:19

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 04/20] drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height

On Wed, Apr 17, 2019 at 12:47:48PM +0200, Maarten Lankhorst wrote:
> > +/**
> > + * drm_format_info_plane_width - width of the plane given the first plane
> > + * @format: pixel format info
> > + * @width: width of the first plane
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The width of @plane, given that the width of the first plane is @width.
> > + */
> > +static inline
> > +int drm_format_info_plane_width(const struct drm_format_info *info, int width,
> > + int plane)
> > +{
> > + if (!info || plane >= info->num_planes)
> > + return 0;
> > +
> > + if (plane == 0)
> > + return width;
> > +
> > + return width / info->hsub;
> > +}
> > +
> > +/**
> > + * drm_format_info_plane_height - height of the plane given the first plane
> > + * @format: pixel format info
> > + * @height: height of the first plane
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The height of @plane, given that the height of the first plane is @height.
> > + */
> > +static inline
> > +int drm_format_info_plane_height(const struct drm_format_info *info, int height,
> > + int plane)
> > +{
> > + if (!info || plane >= info->num_planes)
> > + return 0;
> > +
> > + if (plane == 0)
> > + return height;
> > +
> > + return height / info->vsub;
> > +}
>
> Why the null checks? None of the other inlines for drm_format_info
> perform them.

Unless I'm mistaken, the subsampling only applies to the planes with
the chrominance, which are always >= 1. Therefore the plane 0 is
always the luminance, to which the subsampling doesn't apply.

Or are you talking about something else?

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (1.71 kB)
signature.asc (235.00 B)
Download all attachments

2019-04-17 11:11:48

by Maarten Lankhorst

[permalink] [raw]
Subject: Re: [PATCH 04/20] drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height

Op 17-04-2019 om 13:01 schreef Maxime Ripard:
> On Wed, Apr 17, 2019 at 12:47:48PM +0200, Maarten Lankhorst wrote:
>>> +/**
>>> + * drm_format_info_plane_width - width of the plane given the first plane
>>> + * @format: pixel format info
>>> + * @width: width of the first plane
>>> + * @plane: plane index
>>> + *
>>> + * Returns:
>>> + * The width of @plane, given that the width of the first plane is @width.
>>> + */
>>> +static inline
>>> +int drm_format_info_plane_width(const struct drm_format_info *info, int width,
>>> + int plane)
>>> +{
>>> + if (!info || plane >= info->num_planes)
>>> + return 0;
>>> +
>>> + if (plane == 0)
>>> + return width;
>>> +
>>> + return width / info->hsub;
>>> +}
>>> +
>>> +/**
>>> + * drm_format_info_plane_height - height of the plane given the first plane
>>> + * @format: pixel format info
>>> + * @height: height of the first plane
>>> + * @plane: plane index
>>> + *
>>> + * Returns:
>>> + * The height of @plane, given that the height of the first plane is @height.
>>> + */
>>> +static inline
>>> +int drm_format_info_plane_height(const struct drm_format_info *info, int height,
>>> + int plane)
>>> +{
>>> + if (!info || plane >= info->num_planes)
>>> + return 0;
>>> +
>>> + if (plane == 0)
>>> + return height;
>>> +
>>> + return height / info->vsub;
>>> +}
>> Why the null checks? None of the other inlines for drm_format_info
>> perform them.
> Unless I'm mistaken, the subsampling only applies to the planes with
> the chrominance, which are always >= 1. Therefore the plane 0 is
> always the luminance, to which the subsampling doesn't apply.
>
> Or are you talking about something else?


The info == NULL check. :)

2019-04-17 12:26:49

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Wed, 2019-04-17 at 09:54 +0200, Maxime Ripard wrote:
> Hi,
>
> DRM comes with an extensive format support to retrieve the various
> parameters associated with a given format (such as the subsampling, or the
> bits per pixel), as well as some helpers and utilities to ease the driver
> development.
>
> v4l2, on the other side, doesn't provide such facilities, leaving each
> driver reimplement a subset of the formats parameters for the one supported
> by that particular driver. This leads to a lot of duplication and
> boilerplate code in the v4l2 drivers.
>
> This series tries to address this by moving the DRM format API into lib and
> turning it into a more generic API. In order to do this, we've needed to do
> some preliminary changes on the DRM drivers, then moved the API and finally
> converted a v4l2 driver to give an example of how such library could be
> used.
>
> Let me know what you think,
> Maxime

Here is one general suggestion: calling the new library and functions
and formats "pixel format" instead of "image format" since this is the
most widely-used terminology (see the pixel format guide) and also the
one that (personally) feels most accurate.

What do you think?

Cheers,

Paul

> Changes from RFC:
> - Rebased on next
> - Fixed the various formats mapping
> - Added tags
> - Did most of the formats functions as inline functions
> - Used a consistent prefix for all the utilities functions
> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> arm64 and x86_64
> - Fixed out of array bounds warnings in the image_format_info_block_*
> functions
> - Added License and copyright headers on missing files
>
> Maxime Ripard (20):
> drm: Remove users of drm_format_num_planes
> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> drm: Replace instances of drm_format_info by drm_get_format_info
> lib: Add video format information library
> drm/fb: Move from drm_format_info to image_format_info
> drm/malidp: Convert to generic image format library
> drm/client: Convert to generic image format library
> drm/exynos: Convert to generic image format library
> drm/i915: Convert to generic image format library
> drm/ipuv3: Convert to generic image format library
> drm/msm: Convert to generic image format library
> drm/omap: Convert to generic image format library
> drm/rockchip: Convert to generic image format library
> drm/tegra: Convert to generic image format library
> drm/fourcc: Remove old DRM format API
> lib: image-formats: Add v4l2 formats support
> lib: image-formats: Add more functions
> media: sun6i: Convert to the image format API
>
> drivers/gpu/drm/Kconfig | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +-
> drivers/gpu/drm/arm/malidp_drv.c | 3 +-
> drivers/gpu/drm/arm/malidp_hw.c | 3 +-
> drivers/gpu/drm/arm/malidp_mw.c | 2 +-
> drivers/gpu/drm/arm/malidp_planes.c | 20 +-
> drivers/gpu/drm/armada/armada_fb.c | 3 +-
> drivers/gpu/drm/armada/armada_overlay.c | 2 +-
> drivers/gpu/drm/armada/armada_plane.c | 2 +-
> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 11 +-
> drivers/gpu/drm/bochs/bochs.h | 4 +-
> drivers/gpu/drm/bochs/bochs_hw.c | 2 +-
> drivers/gpu/drm/drm_client.c | 7 +-
> drivers/gpu/drm/drm_fb_cma_helper.c | 4 +-
> drivers/gpu/drm/drm_fb_helper.c | 14 +-
> drivers/gpu/drm/drm_format_helper.c | 4 +-
> drivers/gpu/drm/drm_fourcc.c | 345 +-----
> drivers/gpu/drm/drm_framebuffer.c | 10 +-
> drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.h | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_scaler.c | 3 +-
> drivers/gpu/drm/gma500/framebuffer.c | 4 +-
> drivers/gpu/drm/i915/i915_drv.h | 6 +-
> drivers/gpu/drm/i915/intel_display.c | 14 +-
> drivers/gpu/drm/i915/intel_pm.c | 6 +-
> drivers/gpu/drm/i915/intel_sprite.c | 3 +-
> drivers/gpu/drm/imx/ipuv3-plane.c | 19 +-
> drivers/gpu/drm/mediatek/mtk_drm_fb.c | 8 +-
> drivers/gpu/drm/meson/meson_overlay.c | 14 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 11 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 4 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 25 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 8 +-
> drivers/gpu/drm/msm/msm_fb.c | 18 +-
> drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +-
> drivers/gpu/drm/omapdrm/omap_fb.c | 15 +-
> drivers/gpu/drm/radeon/radeon_fb.c | 4 +-
> drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 17 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 +-
> drivers/gpu/drm/selftests/Makefile | 3 +-
> drivers/gpu/drm/selftests/drm_modeset_selftests.h | 3 +-
> drivers/gpu/drm/selftests/test-drm_format.c | 280 +----
> drivers/gpu/drm/selftests/test-drm_modeset_common.h | 3 +-
> drivers/gpu/drm/stm/ltdc.c | 2 +-
> drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +-
> drivers/gpu/drm/sun4i/sun4i_frontend.c | 18 +-
> drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 5 +-
> drivers/gpu/drm/tegra/fb.c | 14 +-
> drivers/gpu/drm/tegra/plane.c | 4 +-
> drivers/gpu/drm/vc4/vc4_plane.c | 15 +-
> drivers/gpu/drm/zte/zx_plane.c | 6 +-
> drivers/gpu/ipu-v3/ipu-pre.c | 3 +-
> drivers/gpu/ipu-v3/ipu-prg.c | 3 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 89 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 49 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 6 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c | 11 +-
> include/drm/drm_fourcc.h | 219 +---
> include/drm/drm_framebuffer.h | 4 +-
> include/drm/drm_mode_config.h | 5 +-
> include/linux/image-formats.h | 438 ++++++-
> lib/Kconfig | 7 +-
> lib/Makefile | 3 +-
> lib/image-formats-selftests.c | 325 +++++-
> lib/image-formats.c | 717 ++++++++++-
> 70 files changed, 1740 insertions(+), 1174 deletions(-)
> delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
> create mode 100644 include/linux/image-formats.h
> create mode 100644 lib/image-formats-selftests.c
> create mode 100644 lib/image-formats.c
>
> base-commit: de3c659c83ce88d495f2a36397071fdd0a337345
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-17 12:37:30

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 06/20] lib: Add video format information library

Hi,

On Wed, 2019-04-17 at 09:54 +0200, Maxime Ripard wrote:
> Move the DRM formats API to turn this into a more generic image formats API
> to be able to leverage it into some other places of the kernel, such as
> v4l2 drivers.

See a few comments below.

> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> include/linux/image-formats.h | 387 +++++++++++++++++++++-
> lib/Kconfig | 7 +-
> lib/Makefile | 3 +-
> lib/image-formats-selftests.c | 325 +++++++++++++++++-
> lib/image-formats.c | 655 +++++++++++++++++++++++++++++++++++-
> 5 files changed, 1377 insertions(+)
> create mode 100644 include/linux/image-formats.h
> create mode 100644 lib/image-formats-selftests.c
> create mode 100644 lib/image-formats.c
>
> diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> new file mode 100644
> index 000000000000..ec43d9f9a527
> --- /dev/null
> +++ b/include/linux/image-formats.h
> @@ -0,0 +1,387 @@
> +/*
> + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> + *
> + * 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.
> + */
> +
> +#ifndef _IMAGE_FORMATS_H_
> +#define _IMAGE_FORMATS_H_
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +
> +/**
> + * struct image_format_info - information about a image format
> + */
> +struct image_format_info {
> + union {
> + /**
> + * @drm_fmt:
> + *
> + * DRM 4CC format identifier (DRM_FORMAT_*)
> + */
> + u32 drm_fmt;

Could we call this one format_drm for consistency with the one below?

> +
> + /**
> + * @format:
> + *
> + * DRM 4CC format identifier (DRM_FORMAT_*). Kept
> + * around for compatibility reasons with the current
> + * DRM drivers.
> + */
> + u32 format;
> + };
> +
> + /**
> + * @depth:
> + *
> + * Color depth (number of bits per pixel excluding padding bits),
> + * valid for a subset of RGB formats only. This is a legacy field, do
> + * not use in new code and set to 0 for new formats.
> + */
> + u8 depth;
> +
> + /** @num_planes: Number of color planes (1 to 3) */
> + u8 num_planes;
> +
> + union {
> + /**
> + * @cpp:
> + *
> + * Number of bytes per pixel (per plane), this is aliased with
> + * @char_per_block. It is deprecated in favour of using the
> + * triplet @char_per_block, @block_w, @block_h for better
> + * describing the pixel format.
> + */
> + u8 cpp[3];
> +
> + /**
> + * @char_per_block:
> + *
> + * Number of bytes per block (per plane), where blocks are
> + * defined as a rectangle of pixels which are stored next to
> + * each other in a byte aligned memory region. Together with
> + * @block_w and @block_h this is used to properly describe tiles
> + * in tiled formats or to describe groups of pixels in packed
> + * formats for which the memory needed for a single pixel is not
> + * byte aligned.
> + *
> + * @cpp has been kept for historical reasons because there are
> + * a lot of places in drivers where it's used. In drm core for
> + * generic code paths the preferred way is to use
> + * @char_per_block, image_format_info_block_width() and
> + * image_format_info_block_height() which allows handling both
> + * block and non-block formats in the same way.
> + *
> + * For formats that are intended to be used only with non-linear
> + * modifiers both @cpp and @char_per_block must be 0 in the
> + * generic format table. Drivers could supply accurate
> + * information from their drm_mode_config.get_format_info hook
> + * if they want the core to be validating the pitch.
> + */
> + u8 char_per_block[3];
> + };
> +
> + /**
> + * @block_w:
> + *
> + * Block width in pixels, this is intended to be accessed through
> + * image_format_info_block_width()
> + */
> + u8 block_w[3];
> +
> + /**
> + * @block_h:
> + *
> + * Block height in pixels, this is intended to be accessed through
> + * image_format_info_block_height()
> + */
> + u8 block_h[3];
> +
> + /** @hsub: Horizontal chroma subsampling factor */
> + u8 hsub;
> + /** @vsub: Vertical chroma subsampling factor */
> + u8 vsub;
> +
> + /** @has_alpha: Does the format embeds an alpha component? */
> + bool has_alpha;
> +
> + /** @is_yuv: Is it a YUV format? */
> + bool is_yuv;
> +};
> +
> +/**
> + * image_format_info_is_yuv_packed - check that the format info matches a YUV
> + * format with data laid in a single plane
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a packed YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_packed(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_semiplanar - check that the format info matches a YUV
> + * format with data laid in two planes (luminance and chrominance)
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a semiplanar YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_semiplanar(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 2;
> +}
> +
> +/**
> + * image_format_info_is_yuv_planar - check that the format info matches a YUV
> + * format with data laid in three planes (one for each YUV component)
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a planar YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_planar(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 3;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_410 - check that the format info matches a
> + * YUV format with 4:1:0 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:1:0
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_410(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 4 && info->vsub == 4;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_411 - check that the format info matches a
> + * YUV format with 4:1:1 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:1:1
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_411(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 4 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_420 - check that the format info matches a
> + * YUV format with 4:2:0 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:2:0
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_420(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 2 && info->vsub == 2;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_422 - check that the format info matches a
> + * YUV format with 4:2:2 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:2:2
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_422(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 2 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_444 - check that the format info matches a
> + * YUV format with 4:4:4 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:4:4
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_444(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 1 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_plane_cpp - determine the bytes per pixel value
> + * @format: pixel format info
> + * @plane: plane index
> + *
> + * Returns:
> + * The bytes per pixel value for the specified plane.
> + */
> +static inline
> +int image_format_info_plane_cpp(const struct image_format_info *info, int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + return info->cpp[plane];
> +}
> +
> +/**
> + * image_format_info_plane_width - width of the plane given the first plane
> + * @format: pixel format info
> + * @width: width of the first plane
> + * @plane: plane index
> + *
> + * Returns:
> + * The width of @plane, given that the width of the first plane is @width.
> + */
> +static inline
> +int image_format_info_plane_width(const struct image_format_info *info, int width,
> + int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + if (plane == 0)
> + return width;
> +
> + return width / info->hsub;

I think you should DIV_ROUND_UP here.

> +}
> +
> +/**
> + * image_format_info_plane_height - height of the plane given the first plane
> + * @format: pixel format info
> + * @height: height of the first plane
> + * @plane: plane index
> + *
> + * Returns:
> + * The height of @plane, given that the height of the first plane is @height.
> + */
> +static inline
> +int image_format_info_plane_height(const struct image_format_info *info, int height,
> + int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + if (plane == 0)
> + return height;
> +
> + return height / info->vsub;

Ditto.

> +}
> +
> +/**
> + * image_format_info_block_width - width in pixels of block.
> + * @format: pointer to the image_format_info
> + * @plane: plane index
> + *
> + * Returns:
> + * The width in pixels of a block, depending on the plane index.
> + */
> +static inline
> +unsigned int image_format_info_block_width(const struct image_format_info *format,
> + int plane)
> +{
> + if (!format)
> + return 0;
> +
> + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> + return 0;
> +
> + if (plane >= format->num_planes)
> + return 0;
> +
> + if (!format->block_w[plane])
> + return 1;
> +
> + return format->block_w[plane];
> +}
> +
> +/**
> + * image_format_info_block_height - height in pixels of a block
> + * @info: pointer to the image_format_info
> + * @plane: plane index
> + *
> + * Returns:
> + * The height in pixels of a block, depending on the plane index.
> + */
> +static inline
> +unsigned int image_format_info_block_height(const struct image_format_info *format,
> + int plane)
> +{
> + if (!format)
> + return 0;
> +
> + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> + return 0;
> +
> + if (plane >= format->num_planes)
> + return 0;
> +
> + if (!format->block_h[plane])
> + return 1;
> +
> + return format->block_h[plane];
> +}
> +
> +/**
> + * image_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.
> + */
> +static inline
> +uint64_t image_format_info_min_pitch(const struct image_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],
> + image_format_info_block_width(info, plane) *
> + image_format_info_block_height(info, plane));

I'm not sure I understand how this works: char_per_block is 0 for
almost all formats and this doesn't take in account the cpp. Am I
missing something here?

Also, this might be a good occasion to discuss what meaning we want to
give "stride" and "pitch": should one be in bytes and the other in bit,
etc? I keep forgetting what each API expects.

Cheers,

Paul

> +}
> +
> +const struct image_format_info *__image_format_drm_lookup(u32 drm);
> +const struct image_format_info *image_format_drm_lookup(u32 drm);
> +
> +#endif /* _IMAGE_FORMATS_H_ */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index fb453afff32e..9a0160d3123b 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -625,3 +625,10 @@ config GENERIC_LIB_UCMPDI2
>
> config OBJAGG
> tristate "objagg" if COMPILE_TEST
> +
> +config IMAGE_FORMATS
> + bool
> +
> +config IMAGE_FORMATS_SELFTESTS
> + tristate "Test image format functions"
> + depends on IMAGE_FORMATS
> diff --git a/lib/Makefile b/lib/Makefile
> index 6996d2b9f401..203336b91248 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -280,3 +280,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
> obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
> obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
> obj-$(CONFIG_OBJAGG) += objagg.o
> +
> +obj-$(CONFIG_IMAGE_FORMATS) += image-formats.o
> +obj-$(CONFIG_IMAGE_FORMATS_SELFTESTS) += image-formats-selftests.o
> diff --git a/lib/image-formats-selftests.c b/lib/image-formats-selftests.c
> new file mode 100644
> index 000000000000..d0f0011b535e
> --- /dev/null
> +++ b/lib/image-formats-selftests.c
> @@ -0,0 +1,325 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Test cases for the image_format functions
> + */
> +
> +#define pr_fmt(fmt) "image_format: " fmt
> +
> +#include <linux/errno.h>
> +#include <linux/image-formats.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <drm/drm_fourcc.h>
> +
> +#define FAIL(test, msg, ...) \
> + do { \
> + if (test) { \
> + pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
> + return -EINVAL; \
> + } \
> + } while (0)
> +
> +#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
> +
> +static int test_image_format_info_block_width(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_block_width(info, 0) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> +
> + /* Test 1 plane format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> + FAIL_ON(image_format_info_block_width(info, 2) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test 3 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> + FAIL_ON(image_format_info_block_width(info, 2) != 1);
> + FAIL_ON(image_format_info_block_width(info, 3) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test a tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 2);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + return 0;
> +}
> +
> +static int test_image_format_info_block_height(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_block_height(info, 0) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> +
> + /* Test 1 plane format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> + FAIL_ON(image_format_info_block_height(info, 2) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test 3 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> + FAIL_ON(image_format_info_block_height(info, 2) != 1);
> + FAIL_ON(image_format_info_block_height(info, 3) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test a tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 2);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + return 0;
> +}
> +
> +static int test_image_format_info_min_pitch(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + /* Test 1 plane 8 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_RGB332);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1));
> +
> + /* Test 1 plane 16 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1) * 2);
> +
> + /* Test 1 plane 24 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_RGB888);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 3);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 6);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 3072);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 5760);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 12288);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2013);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 3);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 3);
> +
> + /* Test 1 plane 32 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_ABGR8888);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 8);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 2560);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 7680);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 16384);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2684);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 4);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 672);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1));
> + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1));
> +
> + /* Test 3 planes 8 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 3, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 320);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 320) != 320);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 512);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 512) != 512);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 960);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 960) != 960);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 2048) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 336);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 336) != 336);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX / 2 + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX / 2 + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> + FAIL_ON(image_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> +
> + /* Test tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L2);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 2);
> +
> + return 0;
> +}
> +
> +#define selftest(test) { .name = #test, .func = test, }
> +
> +static struct image_format_test {
> + char *name;
> + int (*func)(void);
> +} tests[] = {
> + selftest(test_image_format_info_block_height),
> + selftest(test_image_format_info_block_width),
> + selftest(test_image_format_info_min_pitch),
> +};
> +
> +static int __init image_format_test_init(void)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(tests); i++) {
> + struct image_format_test *test = &tests[i];
> + int ret;
> +
> + ret = test->func();
> + if (ret) {
> + pr_err("Failed test %s\n", test->name);
> + return ret;
> + }
> + }
> +
> + pr_info("All tests executed properly.\n");
> + return 0;
> +}
> +module_init(image_format_test_init);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_AUTHOR("Maxime Ripard <[email protected]>");
> +MODULE_LICENSE("GPL");
> diff --git a/lib/image-formats.c b/lib/image-formats.c
> new file mode 100644
> index 000000000000..1e52a7410222
> --- /dev/null
> +++ b/lib/image-formats.c
> @@ -0,0 +1,655 @@
> +/*
> + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> + *
> + * 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/image-formats.h>
> +#include <linux/kernel.h>
> +#include <linux/math64.h>
> +
> +#include <uapi/drm/drm_fourcc.h>
> +
> +static const struct image_format_info formats[] = {
> + {
> + .drm_fmt = DRM_FORMAT_C8,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB332,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR233,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB565,
> + .depth = 16,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR565,
> + .depth = 16,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 3, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 3, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB565_A8,
> + .depth = 24,
> + .num_planes = 2,
> + .cpp = { 2, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR565_A8,
> + .depth = 24,
> + .num_planes = 2,
> + .cpp = { 2, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 3, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 3, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV410,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 4,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU410,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 4,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV411,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU411,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV420,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU420,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV422,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU422,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV444,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU444,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV12,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV21,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV16,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV61,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV24,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV42,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUYV,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVYU,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_UYVY,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_VYUY,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XYUV8888,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_AYUV,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + },
> +};
> +
> +#define __image_format_lookup(_field, _fmt) \
> + ({ \
> + const struct image_format_info *format = NULL; \
> + unsigned i; \
> + \
> + for (i = 0; i < ARRAY_SIZE(formats); i++) \
> + if (formats[i]._field == _fmt) \
> + format = &formats[i]; \
> + \
> + format; \
> + })
> +
> +/**
> + * __image_format_drm_lookup - query information for a given format
> + * @drm: DRM fourcc pixel format (DRM_FORMAT_*)
> + *
> + * The caller should only pass a supported pixel format to this function.
> + *
> + * Returns:
> + * The instance of struct image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *__image_format_drm_lookup(u32 drm)
> +{
> + return __image_format_lookup(drm_fmt, drm);
> +}
> +EXPORT_SYMBOL(__image_format_drm_lookup);
> +
> +/**
> + * image_format_drm_lookup - query information for a given format
> + * @drm: DRM fourcc 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 image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *image_format_drm_lookup(u32 drm)
> +{
> + const struct image_format_info *format;
> +
> + format = __image_format_drm_lookup(drm);
> +
> + WARN_ON(!format);
> + return format;
> +}
> +EXPORT_SYMBOL(image_format_drm_lookup);
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-17 12:39:45

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Wed, 2019-04-17 at 09:54 +0200, Maxime Ripard wrote:
> Hi,
>
> DRM comes with an extensive format support to retrieve the various
> parameters associated with a given format (such as the subsampling, or the
> bits per pixel), as well as some helpers and utilities to ease the driver
> development.
>
> v4l2, on the other side, doesn't provide such facilities, leaving each
> driver reimplement a subset of the formats parameters for the one supported
> by that particular driver. This leads to a lot of duplication and
> boilerplate code in the v4l2 drivers.
>
> This series tries to address this by moving the DRM format API into lib and
> turning it into a more generic API. In order to do this, we've needed to do
> some preliminary changes on the DRM drivers, then moved the API and finally
> converted a v4l2 driver to give an example of how such library could be
> used.
>
> Let me know what you think,

Another thing to consider would be using unsigned ints for the plane
index so we can avoid < 0 checks all over the place.

What do you think?

Cheers,

Paul

> Maxime
>
> Changes from RFC:
> - Rebased on next
> - Fixed the various formats mapping
> - Added tags
> - Did most of the formats functions as inline functions
> - Used a consistent prefix for all the utilities functions
> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> arm64 and x86_64
> - Fixed out of array bounds warnings in the image_format_info_block_*
> functions
> - Added License and copyright headers on missing files
>
> Maxime Ripard (20):
> drm: Remove users of drm_format_num_planes
> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> drm: Replace instances of drm_format_info by drm_get_format_info
> lib: Add video format information library
> drm/fb: Move from drm_format_info to image_format_info
> drm/malidp: Convert to generic image format library
> drm/client: Convert to generic image format library
> drm/exynos: Convert to generic image format library
> drm/i915: Convert to generic image format library
> drm/ipuv3: Convert to generic image format library
> drm/msm: Convert to generic image format library
> drm/omap: Convert to generic image format library
> drm/rockchip: Convert to generic image format library
> drm/tegra: Convert to generic image format library
> drm/fourcc: Remove old DRM format API
> lib: image-formats: Add v4l2 formats support
> lib: image-formats: Add more functions
> media: sun6i: Convert to the image format API
>
> drivers/gpu/drm/Kconfig | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +-
> drivers/gpu/drm/arm/malidp_drv.c | 3 +-
> drivers/gpu/drm/arm/malidp_hw.c | 3 +-
> drivers/gpu/drm/arm/malidp_mw.c | 2 +-
> drivers/gpu/drm/arm/malidp_planes.c | 20 +-
> drivers/gpu/drm/armada/armada_fb.c | 3 +-
> drivers/gpu/drm/armada/armada_overlay.c | 2 +-
> drivers/gpu/drm/armada/armada_plane.c | 2 +-
> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 11 +-
> drivers/gpu/drm/bochs/bochs.h | 4 +-
> drivers/gpu/drm/bochs/bochs_hw.c | 2 +-
> drivers/gpu/drm/drm_client.c | 7 +-
> drivers/gpu/drm/drm_fb_cma_helper.c | 4 +-
> drivers/gpu/drm/drm_fb_helper.c | 14 +-
> drivers/gpu/drm/drm_format_helper.c | 4 +-
> drivers/gpu/drm/drm_fourcc.c | 345 +-----
> drivers/gpu/drm/drm_framebuffer.c | 10 +-
> drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.h | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_scaler.c | 3 +-
> drivers/gpu/drm/gma500/framebuffer.c | 4 +-
> drivers/gpu/drm/i915/i915_drv.h | 6 +-
> drivers/gpu/drm/i915/intel_display.c | 14 +-
> drivers/gpu/drm/i915/intel_pm.c | 6 +-
> drivers/gpu/drm/i915/intel_sprite.c | 3 +-
> drivers/gpu/drm/imx/ipuv3-plane.c | 19 +-
> drivers/gpu/drm/mediatek/mtk_drm_fb.c | 8 +-
> drivers/gpu/drm/meson/meson_overlay.c | 14 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 11 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 4 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 25 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 8 +-
> drivers/gpu/drm/msm/msm_fb.c | 18 +-
> drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +-
> drivers/gpu/drm/omapdrm/omap_fb.c | 15 +-
> drivers/gpu/drm/radeon/radeon_fb.c | 4 +-
> drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 17 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 +-
> drivers/gpu/drm/selftests/Makefile | 3 +-
> drivers/gpu/drm/selftests/drm_modeset_selftests.h | 3 +-
> drivers/gpu/drm/selftests/test-drm_format.c | 280 +----
> drivers/gpu/drm/selftests/test-drm_modeset_common.h | 3 +-
> drivers/gpu/drm/stm/ltdc.c | 2 +-
> drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +-
> drivers/gpu/drm/sun4i/sun4i_frontend.c | 18 +-
> drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 5 +-
> drivers/gpu/drm/tegra/fb.c | 14 +-
> drivers/gpu/drm/tegra/plane.c | 4 +-
> drivers/gpu/drm/vc4/vc4_plane.c | 15 +-
> drivers/gpu/drm/zte/zx_plane.c | 6 +-
> drivers/gpu/ipu-v3/ipu-pre.c | 3 +-
> drivers/gpu/ipu-v3/ipu-prg.c | 3 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 89 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 49 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 6 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c | 11 +-
> include/drm/drm_fourcc.h | 219 +---
> include/drm/drm_framebuffer.h | 4 +-
> include/drm/drm_mode_config.h | 5 +-
> include/linux/image-formats.h | 438 ++++++-
> lib/Kconfig | 7 +-
> lib/Makefile | 3 +-
> lib/image-formats-selftests.c | 325 +++++-
> lib/image-formats.c | 717 ++++++++++-
> 70 files changed, 1740 insertions(+), 1174 deletions(-)
> delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
> create mode 100644 include/linux/image-formats.h
> create mode 100644 lib/image-formats-selftests.c
> create mode 100644 lib/image-formats.c
>
> base-commit: de3c659c83ce88d495f2a36397071fdd0a337345
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-17 12:41:00

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 19/20] lib: image-formats: Add more functions

Hi,

On Wed, 2019-04-17 at 09:54 +0200, Maxime Ripard wrote:
> V4L2 drivers typically need a few more helpers compared to DRM drivers, so
> let's add them.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> include/linux/image-formats.h | 42 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 42 insertions(+)
>
> diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> index b78b8e861fc9..a2cf3528bd31 100644
> --- a/include/linux/image-formats.h
> +++ b/include/linux/image-formats.h
> @@ -388,6 +388,48 @@ uint64_t image_format_info_min_pitch(const struct image_format_info *info,
> image_format_info_block_height(info, plane));
> }
>
> +/**
> + * image_format_info_plane_stride - determine the stride value
> + * @format: pointer to the image_format_info
> + * @width: plane width
> + * @plane: plane index
> + *
> + * Returns:
> + * The bytes per pixel value for the specified plane.

Looks like this needs to be updated to "bytes per line" ;)

Cheers,

Paul

> + */
> +static inline
> +unsigned int image_format_info_plane_stride(const struct image_format_info *format,
> + unsigned int width, int plane)
> +{
> + if (!format || plane >= format->num_planes)
> + return 0;
> +
> + return image_format_info_plane_width(format, width, plane) *
> + image_format_info_plane_cpp(format, plane);
> +}
> +
> +/**
> + * image_format_info_plane_size - determine the size value
> + * @format: pointer to the image_format_info
> + * @width: plane width
> + * @height: plane width
> + * @plane: plane index
> + *
> + * Returns:
> + * The size of the plane buffer.
> + */
> +static inline
> +unsigned int image_format_info_plane_size(const struct image_format_info *format,
> + unsigned int width, unsigned int height,
> + int plane)
> +{
> + if (!format || plane >= format->num_planes)
> + return 0;
> +
> + return image_format_info_plane_stride(format, width, plane) *
> + image_format_info_plane_height(format, height, plane);
> +}
> +
> const struct image_format_info *__image_format_drm_lookup(u32 drm);
> const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2);
> const struct image_format_info *image_format_drm_lookup(u32 drm);
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-17 12:44:07

by Sakari Ailus

[permalink] [raw]
Subject: Re: [PATCH 19/20] lib: image-formats: Add more functions

Hi Maxime,

On Wed, Apr 17, 2019 at 09:54:45AM +0200, Maxime Ripard wrote:
> V4L2 drivers typically need a few more helpers compared to DRM drivers, so
> let's add them.
>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> include/linux/image-formats.h | 42 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 42 insertions(+)
>
> diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> index b78b8e861fc9..a2cf3528bd31 100644
> --- a/include/linux/image-formats.h
> +++ b/include/linux/image-formats.h
> @@ -388,6 +388,48 @@ uint64_t image_format_info_min_pitch(const struct image_format_info *info,
> image_format_info_block_height(info, plane));
> }
>
> +/**
> + * image_format_info_plane_stride - determine the stride value
> + * @format: pointer to the image_format_info
> + * @width: plane width
> + * @plane: plane index
> + *
> + * Returns:
> + * The bytes per pixel value for the specified plane.

In V4L2 the bytesperline (stride) value is user configurable and is also
subject to hardware capabilities. So effectively this makes what the
function returns a minimum value for a given format. I think you could add
this to the documentation. This is also not the number of bytes per pixel,
as suggested above. So, e.g.

Returns the minimum number of bytes between two consecutive lines.

> + */
> +static inline
> +unsigned int image_format_info_plane_stride(const struct image_format_info *format,
> + unsigned int width, int plane)
> +{
> + if (!format || plane >= format->num_planes)
> + return 0;
> +
> + return image_format_info_plane_width(format, width, plane) *
> + image_format_info_plane_cpp(format, plane);
> +}
> +
> +/**
> + * image_format_info_plane_size - determine the size value
> + * @format: pointer to the image_format_info
> + * @width: plane width
> + * @height: plane width
> + * @plane: plane index
> + *
> + * Returns:
> + * The size of the plane buffer.

Similarly:

Returns the minimum size of the plane buffer.

With these,

Acked-by: Sakari Ailus <[email protected]>

> + */
> +static inline
> +unsigned int image_format_info_plane_size(const struct image_format_info *format,
> + unsigned int width, unsigned int height,
> + int plane)
> +{
> + if (!format || plane >= format->num_planes)
> + return 0;
> +
> + return image_format_info_plane_stride(format, width, plane) *
> + image_format_info_plane_height(format, height, plane);
> +}
> +
> const struct image_format_info *__image_format_drm_lookup(u32 drm);
> const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2);
> const struct image_format_info *image_format_drm_lookup(u32 drm);

--
Sakari Ailus
[email protected]

2019-04-17 12:50:04

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 06/20] lib: Add video format information library

Hi,

On Wed, Apr 17, 2019 at 02:34:54PM +0200, Paul Kocialkowski wrote:
> > +struct image_format_info {
> > + union {
> > + /**
> > + * @drm_fmt:
> > + *
> > + * DRM 4CC format identifier (DRM_FORMAT_*)
> > + */
> > + u32 drm_fmt;
>
> Could we call this one format_drm for consistency with the one below?

The deprecated "format" field will go away at some point, so I'm not
sure the consistency is an argument there.

> > +/**
> > + * image_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.
> > + */
> > +static inline
> > +uint64_t image_format_info_min_pitch(const struct image_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],
> > + image_format_info_block_width(info, plane) *
> > + image_format_info_block_height(info, plane));
>
> I'm not sure I understand how this works: char_per_block is 0 for
> almost all formats and this doesn't take in account the cpp. Am I
> missing something here?

I guess it doesn't. That's the DRM function here, without any
modification, but from a quick look at the current users of that
function, there's nobody that uses the value directly.

So you might be right there.

> Also, this might be a good occasion to discuss what meaning we want to
> give "stride" and "pitch": should one be in bytes and the other in bit,
> etc? I keep forgetting what each API expects.

pitch is documented as bytes, and the function computing the stride I
added did too. I'll remove the stride one.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (2.03 kB)
signature.asc (235.00 B)
Download all attachments

2019-04-17 13:14:22

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 04/20] drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height

On Wed, Apr 17, 2019 at 01:10:33PM +0200, Maarten Lankhorst wrote:
> Op 17-04-2019 om 13:01 schreef Maxime Ripard:
> > On Wed, Apr 17, 2019 at 12:47:48PM +0200, Maarten Lankhorst wrote:
> >>> +/**
> >>> + * drm_format_info_plane_width - width of the plane given the first plane
> >>> + * @format: pixel format info
> >>> + * @width: width of the first plane
> >>> + * @plane: plane index
> >>> + *
> >>> + * Returns:
> >>> + * The width of @plane, given that the width of the first plane is @width.
> >>> + */
> >>> +static inline
> >>> +int drm_format_info_plane_width(const struct drm_format_info *info, int width,
> >>> + int plane)
> >>> +{
> >>> + if (!info || plane >= info->num_planes)
> >>> + return 0;
> >>> +
> >>> + if (plane == 0)
> >>> + return width;
> >>> +
> >>> + return width / info->hsub;
> >>> +}
> >>> +
> >>> +/**
> >>> + * drm_format_info_plane_height - height of the plane given the first plane
> >>> + * @format: pixel format info
> >>> + * @height: height of the first plane
> >>> + * @plane: plane index
> >>> + *
> >>> + * Returns:
> >>> + * The height of @plane, given that the height of the first plane is @height.
> >>> + */
> >>> +static inline
> >>> +int drm_format_info_plane_height(const struct drm_format_info *info, int height,
> >>> + int plane)
> >>> +{
> >>> + if (!info || plane >= info->num_planes)
> >>> + return 0;
> >>> +
> >>> + if (plane == 0)
> >>> + return height;
> >>> +
> >>> + return height / info->vsub;
> >>> +}
> >> Why the null checks? None of the other inlines for drm_format_info
> >> perform them.
> > Unless I'm mistaken, the subsampling only applies to the planes with
> > the chrominance, which are always >= 1. Therefore the plane 0 is
> > always the luminance, to which the subsampling doesn't apply.
> >
> > Or are you talking about something else?
>
>
> The info == NULL check. :)

Aaah, sorry :)

That's true, and that's actually the first four patches that change
that behaviour a bit. Previously, drm_format_plane_cpp, _width, and
_height will do the lookup themselves using drm_format_info, and test
whether the pointer returned is null or not.

Patches 3 and 4 removed that lookup but kept the null pointer check.

We could remove it, but there's two downsides for that:

* since the lookup is now effectively pushed to the caller (or the
caller's caller), we would have to check there that the pointer isn't
NULL. That's a lot of boilerplate to add.

* And since this is a generic function, I wouldn't trust the caller
to give a pointer that can be dereferenced right away. This might
be more subjective though.

So I guess we should make sure that we are consistent, but I'd be in
favor of putting that check in all the functions.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (2.85 kB)
signature.asc (235.00 B)
Download all attachments

2019-04-17 13:35:21

by Philipp Zabel

[permalink] [raw]
Subject: Re: [PATCH 02/20] drm: Remove users of drm_format_(horz|vert)_chroma_subsampling

On Wed, 2019-04-17 at 09:54 +0200, Maxime Ripard wrote:
> 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 <[email protected]>
> Reviewed-by: Paul Kocialkowski <[email protected]>
> Signed-off-by: Maxime Ripard <[email protected]>

Reviewed-by: Philipp Zabel <[email protected]>

Just one small suggestion:

[...]
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 20a9c296d027..345d5cb5e956 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -317,21 +317,18 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
> uint32_t src_w, uint32_t src_h, uint32_t dst_w,
> uint32_t dst_h, uint32_t pixel_format)
> {
> + const struct drm_format_info *info = drm_format_info(pixel_format);

The only call site in vop_plane_atomic_update passes fb->format->format
as pixel_format parameter, so this could be simplified even further by
replacing the uint32_t pixelformat argument with a const struct
drm_format_info *info, and passing fb->format directly instead.

regards
Philipp

2019-04-17 14:06:34

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 06/20] lib: Add video format information library

Hi,

On Wed, 2019-04-17 at 14:48 +0200, Maxime Ripard wrote:
> Hi,
>
> On Wed, Apr 17, 2019 at 02:34:54PM +0200, Paul Kocialkowski wrote:
> > > +struct image_format_info {
> > > + union {
> > > + /**
> > > + * @drm_fmt:
> > > + *
> > > + * DRM 4CC format identifier (DRM_FORMAT_*)
> > > + */
> > > + u32 drm_fmt;
> >
> > Could we call this one format_drm for consistency with the one below?
>
> The deprecated "format" field will go away at some point, so I'm not
> sure the consistency is an argument there.

Fair enough then. My point was mostly about format vs fmt, so one
option could be to use "compat_fmt" or such, but do whatever you feel
is right, I don't care too much about it.

> > > +/**
> > > + * image_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.
> > > + */
> > > +static inline
> > > +uint64_t image_format_info_min_pitch(const struct image_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],
> > > + image_format_info_block_width(info, plane) *
> > > + image_format_info_block_height(info, plane));
> >
> > I'm not sure I understand how this works: char_per_block is 0 for
> > almost all formats and this doesn't take in account the cpp. Am I
> > missing something here?
>
> I guess it doesn't. That's the DRM function here, without any
> modification, but from a quick look at the current users of that
> function, there's nobody that uses the value directly.
>
> So you might be right there.
>
> > Also, this might be a good occasion to discuss what meaning we want to
> > give "stride" and "pitch": should one be in bytes and the other in bit,
> > etc? I keep forgetting what each API expects.
>
> pitch is documented as bytes, and the function computing the stride I
> added did too. I'll remove the stride one.

Okay, it seems that I was just confused for no particular reason and
stride, pitch, bytesperline and linesize are all just synonyms. So feel
free to pick whichever you see fit :)

Cheers,

Paul

--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-17 16:35:32

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> Hi,
>
> DRM comes with an extensive format support to retrieve the various
> parameters associated with a given format (such as the subsampling, or the
> bits per pixel), as well as some helpers and utilities to ease the driver
> development.
>
> v4l2, on the other side, doesn't provide such facilities, leaving each
> driver reimplement a subset of the formats parameters for the one supported
> by that particular driver. This leads to a lot of duplication and
> boilerplate code in the v4l2 drivers.
>
> This series tries to address this by moving the DRM format API into lib and
> turning it into a more generic API. In order to do this, we've needed to do
> some preliminary changes on the DRM drivers, then moved the API and finally
> converted a v4l2 driver to give an example of how such library could be
> used.
>
> Let me know what you think,
> Maxime
>
> Changes from RFC:
> - Rebased on next
> - Fixed the various formats mapping
> - Added tags
> - Did most of the formats functions as inline functions
> - Used a consistent prefix for all the utilities functions
> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> arm64 and x86_64
> - Fixed out of array bounds warnings in the image_format_info_block_*
> functions
> - Added License and copyright headers on missing files
>
> Maxime Ripard (20):
> drm: Remove users of drm_format_num_planes
> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> drm: Replace instances of drm_format_info by drm_get_format_info
> lib: Add video format information library
> drm/fb: Move from drm_format_info to image_format_info
> drm/malidp: Convert to generic image format library
> drm/client: Convert to generic image format library
> drm/exynos: Convert to generic image format library
> drm/i915: Convert to generic image format library
> drm/ipuv3: Convert to generic image format library
> drm/msm: Convert to generic image format library
> drm/omap: Convert to generic image format library
> drm/rockchip: Convert to generic image format library
> drm/tegra: Convert to generic image format library
> drm/fourcc: Remove old DRM format API
> lib: image-formats: Add v4l2 formats support
> lib: image-formats: Add more functions
> media: sun6i: Convert to the image format API

In the interest of making myself unpopular: Why move this out of drm?

We do have a bunch of other such shared helpers already (mostly in
drivers/video) for dt videomode and hdmi infoframes, and I'm not super
sure that's going better than keeping it maintained in drm.

Plus the uapi is already that you include drm_fourcc.h to get at these,
dropping the drm prefix isn't going to help I think.

Of course we'd need to make it a separate drm_formats.ko (so that v4l can
use it without dragging in all of drm), and we need to add some fields for
converting to v4l fourcc codes (which are different). But that should be
all possible. And I don't think the drm_ prefix in v4l code is a problem,
it's actually a feature: It makes it really clear that these are the drm
fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
that. That allocation authority is also already baked into various khr/ext
standards, too.

Ofc it'll perpetuate the joke that drm has no meaning anymore as an
abbrevation, but oh welp :-)
-Daniel


>
> drivers/gpu/drm/Kconfig | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +-
> drivers/gpu/drm/arm/malidp_drv.c | 3 +-
> drivers/gpu/drm/arm/malidp_hw.c | 3 +-
> drivers/gpu/drm/arm/malidp_mw.c | 2 +-
> drivers/gpu/drm/arm/malidp_planes.c | 20 +-
> drivers/gpu/drm/armada/armada_fb.c | 3 +-
> drivers/gpu/drm/armada/armada_overlay.c | 2 +-
> drivers/gpu/drm/armada/armada_plane.c | 2 +-
> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 11 +-
> drivers/gpu/drm/bochs/bochs.h | 4 +-
> drivers/gpu/drm/bochs/bochs_hw.c | 2 +-
> drivers/gpu/drm/drm_client.c | 7 +-
> drivers/gpu/drm/drm_fb_cma_helper.c | 4 +-
> drivers/gpu/drm/drm_fb_helper.c | 14 +-
> drivers/gpu/drm/drm_format_helper.c | 4 +-
> drivers/gpu/drm/drm_fourcc.c | 345 +-----
> drivers/gpu/drm/drm_framebuffer.c | 10 +-
> drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_ipp.h | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_scaler.c | 3 +-
> drivers/gpu/drm/gma500/framebuffer.c | 4 +-
> drivers/gpu/drm/i915/i915_drv.h | 6 +-
> drivers/gpu/drm/i915/intel_display.c | 14 +-
> drivers/gpu/drm/i915/intel_pm.c | 6 +-
> drivers/gpu/drm/i915/intel_sprite.c | 3 +-
> drivers/gpu/drm/imx/ipuv3-plane.c | 19 +-
> drivers/gpu/drm/mediatek/mtk_drm_fb.c | 8 +-
> drivers/gpu/drm/meson/meson_overlay.c | 14 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 11 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 4 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 25 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 8 +-
> drivers/gpu/drm/msm/msm_fb.c | 18 +-
> drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +-
> drivers/gpu/drm/omapdrm/omap_fb.c | 15 +-
> drivers/gpu/drm/radeon/radeon_fb.c | 4 +-
> drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 17 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 +-
> drivers/gpu/drm/selftests/Makefile | 3 +-
> drivers/gpu/drm/selftests/drm_modeset_selftests.h | 3 +-
> drivers/gpu/drm/selftests/test-drm_format.c | 280 +----
> drivers/gpu/drm/selftests/test-drm_modeset_common.h | 3 +-
> drivers/gpu/drm/stm/ltdc.c | 2 +-
> drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +-
> drivers/gpu/drm/sun4i/sun4i_frontend.c | 18 +-
> drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 +-
> drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 5 +-
> drivers/gpu/drm/tegra/fb.c | 14 +-
> drivers/gpu/drm/tegra/plane.c | 4 +-
> drivers/gpu/drm/vc4/vc4_plane.c | 15 +-
> drivers/gpu/drm/zte/zx_plane.c | 6 +-
> drivers/gpu/ipu-v3/ipu-pre.c | 3 +-
> drivers/gpu/ipu-v3/ipu-prg.c | 3 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 89 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 49 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 6 +-
> drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c | 11 +-
> include/drm/drm_fourcc.h | 219 +---
> include/drm/drm_framebuffer.h | 4 +-
> include/drm/drm_mode_config.h | 5 +-
> include/linux/image-formats.h | 438 ++++++-
> lib/Kconfig | 7 +-
> lib/Makefile | 3 +-
> lib/image-formats-selftests.c | 325 +++++-
> lib/image-formats.c | 717 ++++++++++-
> 70 files changed, 1740 insertions(+), 1174 deletions(-)
> delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
> create mode 100644 include/linux/image-formats.h
> create mode 100644 lib/image-formats-selftests.c
> create mode 100644 lib/image-formats.c
>
> base-commit: de3c659c83ce88d495f2a36397071fdd0a337345
> --
> git-series 0.9.1
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

2019-04-18 06:24:04

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Daniel,

On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > Hi,
> >
> > DRM comes with an extensive format support to retrieve the various
> > parameters associated with a given format (such as the subsampling, or the
> > bits per pixel), as well as some helpers and utilities to ease the driver
> > development.
> >
> > v4l2, on the other side, doesn't provide such facilities, leaving each
> > driver reimplement a subset of the formats parameters for the one supported
> > by that particular driver. This leads to a lot of duplication and
> > boilerplate code in the v4l2 drivers.
> >
> > This series tries to address this by moving the DRM format API into lib and
> > turning it into a more generic API. In order to do this, we've needed to do
> > some preliminary changes on the DRM drivers, then moved the API and finally
> > converted a v4l2 driver to give an example of how such library could be
> > used.
> >
> > Let me know what you think,
> > Maxime
> >
> > Changes from RFC:
> > - Rebased on next
> > - Fixed the various formats mapping
> > - Added tags
> > - Did most of the formats functions as inline functions
> > - Used a consistent prefix for all the utilities functions
> > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > arm64 and x86_64
> > - Fixed out of array bounds warnings in the image_format_info_block_*
> > functions
> > - Added License and copyright headers on missing files
> >
> > Maxime Ripard (20):
> > drm: Remove users of drm_format_num_planes
> > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > drm: Replace instances of drm_format_info by drm_get_format_info
> > lib: Add video format information library
> > drm/fb: Move from drm_format_info to image_format_info
> > drm/malidp: Convert to generic image format library
> > drm/client: Convert to generic image format library
> > drm/exynos: Convert to generic image format library
> > drm/i915: Convert to generic image format library
> > drm/ipuv3: Convert to generic image format library
> > drm/msm: Convert to generic image format library
> > drm/omap: Convert to generic image format library
> > drm/rockchip: Convert to generic image format library
> > drm/tegra: Convert to generic image format library
> > drm/fourcc: Remove old DRM format API
> > lib: image-formats: Add v4l2 formats support
> > lib: image-formats: Add more functions
> > media: sun6i: Convert to the image format API
>
> In the interest of making myself unpopular: Why move this out of drm?
>
> We do have a bunch of other such shared helpers already (mostly in
> drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> sure that's going better than keeping it maintained in drm.
>
> Plus the uapi is already that you include drm_fourcc.h to get at these,
> dropping the drm prefix isn't going to help I think.
>
> Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> use it without dragging in all of drm), and we need to add some fields for
> converting to v4l fourcc codes (which are different). But that should be
> all possible. And I don't think the drm_ prefix in v4l code is a problem,
> it's actually a feature: It makes it really clear that these are the drm
> fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> that. That allocation authority is also already baked into various khr/ext
> standards, too.

The way I see it, there's a fundamental difference between the UAPI
and the kernel. I don't suggest we change anything about the UAPI: the
drm formats should keep their prefix, drm_fourcc.h can remain that
authority, it's all fine.

Internally however, the long term goal is to share the fourcc's
between DRM and V4L2 for the same formats. It basically means that of
course v4l2 should be using the DRM fourcc when a format exists in DRM
and not v4l2, but also that DRM should use v4l2 fourcc when the format
exists in v4l2 but not DRM, and that is far more likely, given the
already extensive v4l2 formats support.

And given how the current state is a mess in this regard, I'm not too
optimistic about keeping the formats in their relevant frameworks.

Having a shared library, governed by both, will make this far easier,
since it will be easy to discover the formats that are already
supported by the other subsystem.

If we want to keep the current library in DRM, we have two options
then:

- Support all the v4l2 formats in the DRM library, which is
essentially what I'm doing in the last patches. However, that
would require to have the v4l2 developpers also reviewing stuff
there. And given how busy they are, I cannot really see how that
would work.

- Develop the same library from within v4l2. That is really a poor
solution, since the information would be greatly duplicated
between the two, and in terms of maintainance, code, and binary
size that would be duplicated too.

Having it shared allows to easily share, and discover formats from the
other subsystem, and to have a single, unique place where this is
centralized.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2019-04-18 07:54:48

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard <[email protected]> wrote:
>
> Hi Daniel,
>
> On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > Hi,
> > >
> > > DRM comes with an extensive format support to retrieve the various
> > > parameters associated with a given format (such as the subsampling, or the
> > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > development.
> > >
> > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > driver reimplement a subset of the formats parameters for the one supported
> > > by that particular driver. This leads to a lot of duplication and
> > > boilerplate code in the v4l2 drivers.
> > >
> > > This series tries to address this by moving the DRM format API into lib and
> > > turning it into a more generic API. In order to do this, we've needed to do
> > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > converted a v4l2 driver to give an example of how such library could be
> > > used.
> > >
> > > Let me know what you think,
> > > Maxime
> > >
> > > Changes from RFC:
> > > - Rebased on next
> > > - Fixed the various formats mapping
> > > - Added tags
> > > - Did most of the formats functions as inline functions
> > > - Used a consistent prefix for all the utilities functions
> > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > arm64 and x86_64
> > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > functions
> > > - Added License and copyright headers on missing files
> > >
> > > Maxime Ripard (20):
> > > drm: Remove users of drm_format_num_planes
> > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > lib: Add video format information library
> > > drm/fb: Move from drm_format_info to image_format_info
> > > drm/malidp: Convert to generic image format library
> > > drm/client: Convert to generic image format library
> > > drm/exynos: Convert to generic image format library
> > > drm/i915: Convert to generic image format library
> > > drm/ipuv3: Convert to generic image format library
> > > drm/msm: Convert to generic image format library
> > > drm/omap: Convert to generic image format library
> > > drm/rockchip: Convert to generic image format library
> > > drm/tegra: Convert to generic image format library
> > > drm/fourcc: Remove old DRM format API
> > > lib: image-formats: Add v4l2 formats support
> > > lib: image-formats: Add more functions
> > > media: sun6i: Convert to the image format API
> >
> > In the interest of making myself unpopular: Why move this out of drm?
> >
> > We do have a bunch of other such shared helpers already (mostly in
> > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > sure that's going better than keeping it maintained in drm.
> >
> > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > dropping the drm prefix isn't going to help I think.
> >
> > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > use it without dragging in all of drm), and we need to add some fields for
> > converting to v4l fourcc codes (which are different). But that should be
> > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > it's actually a feature: It makes it really clear that these are the drm
> > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > that. That allocation authority is also already baked into various khr/ext
> > standards, too.
>
> The way I see it, there's a fundamental difference between the UAPI
> and the kernel. I don't suggest we change anything about the UAPI: the
> drm formats should keep their prefix, drm_fourcc.h can remain that
> authority, it's all fine.
>
> Internally however, the long term goal is to share the fourcc's
> between DRM and V4L2 for the same formats. It basically means that of
> course v4l2 should be using the DRM fourcc when a format exists in DRM
> and not v4l2, but also that DRM should use v4l2 fourcc when the format
> exists in v4l2 but not DRM, and that is far more likely, given the
> already extensive v4l2 formats support.

Uh no. We did look at v4l fourcc extensively when deciding upon a drm
format identifier space. And a lot of people pushed for the "fourcc is
a standard", when really it's totally not. v4l tends to conflate pixel
format with stuff that we tend to encode in modifiers a lot more.
There's a bunch of reasons we can't just use v4l, and they're as valid
as ever:

- We overlap badly in some areas, so even if fourcc codes match, we
can't use them and need a duplicated DRM_FOURCC code.
- v4l encodes some metadata into the fourcc that we encode elsewhere,
e.g. offset for planar yuv formats, or tiling mode
- drm fourcc code doesn't actually define the drm_format_info
uniquely, drivers can override that (that's an explicit design intent
of modifiers, to allow drivers to add another plane for e.g.
compression information). You'd need to pull that driver knowledge
into your format library.

Iow there's no way we can easily adopt v4l fourcc, except if we do
something like a new addfb flag.

> And given how the current state is a mess in this regard, I'm not too
> optimistic about keeping the formats in their relevant frameworks.
>
> Having a shared library, governed by both, will make this far easier,
> since it will be easy to discover the formats that are already
> supported by the other subsystem.

I think a compat library that (tries to, best effort) convert between
v4l and drm fourcc would make sense. Somewhere in drivers/video, next
to the conversion functions for videomode <-> drm_display_mode
perhaps. That should be useful for drivers.

Unifying the formats themselves, and all the associated metadata is
imo a no-go, and was a pretty conscious decision when we implemented
drm_fourcc a few years back.

> If we want to keep the current library in DRM, we have two options
> then:
>
> - Support all the v4l2 formats in the DRM library, which is
> essentially what I'm doing in the last patches. However, that
> would require to have the v4l2 developpers also reviewing stuff
> there. And given how busy they are, I cannot really see how that
> would work.

Well, if we end up with a common library then yes we need cross
review. There's no way around that. Doesn't matter where exactly that
library is in the filesystem tree, and adding a special MAINTAINERS
entry for anything related to fourcc (both drm and v4l) to make sure
they get cross-posted is easy. No file renaming needed.

> - Develop the same library from within v4l2. That is really a poor
> solution, since the information would be greatly duplicated
> between the two, and in terms of maintainance, code, and binary
> size that would be duplicated too.

It's essentially what we decided to do for drm years back.

> Having it shared allows to easily share, and discover formats from the
> other subsystem, and to have a single, unique place where this is
> centralized.

What I think could work as middle ground:
- Put drm_format stuff into a separate .ko
- Add a MAINTAINERS entry to make sure all things fourcc are cross
posted to both drm and v4l lists. Easy on the drm side, since it's all
separate files. Not sure it's so convenient for v4l uapi.
- Add a conversion library that tries to best-effort map between drm
and v4l formats. On the drm side that most likely means you need
offsets for planes, and modifiers too (since those are implied in some
v4l fourcc). Emphasis on "best effort" i.e. only support as much as
the drivers that use this library need.
- Add drm_fourcc as-needed by these drivers that want to use a unified
format space.

Forcing this unification on everyone otoh is imo way too much.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-04-18 09:03:37

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard <[email protected]> wrote:
> > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > Hi,
> > > >
> > > > DRM comes with an extensive format support to retrieve the various
> > > > parameters associated with a given format (such as the subsampling, or the
> > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > development.
> > > >
> > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > driver reimplement a subset of the formats parameters for the one supported
> > > > by that particular driver. This leads to a lot of duplication and
> > > > boilerplate code in the v4l2 drivers.
> > > >
> > > > This series tries to address this by moving the DRM format API into lib and
> > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > converted a v4l2 driver to give an example of how such library could be
> > > > used.
> > > >
> > > > Let me know what you think,
> > > > Maxime
> > > >
> > > > Changes from RFC:
> > > > - Rebased on next
> > > > - Fixed the various formats mapping
> > > > - Added tags
> > > > - Did most of the formats functions as inline functions
> > > > - Used a consistent prefix for all the utilities functions
> > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > arm64 and x86_64
> > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > functions
> > > > - Added License and copyright headers on missing files
> > > >
> > > > Maxime Ripard (20):
> > > > drm: Remove users of drm_format_num_planes
> > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > lib: Add video format information library
> > > > drm/fb: Move from drm_format_info to image_format_info
> > > > drm/malidp: Convert to generic image format library
> > > > drm/client: Convert to generic image format library
> > > > drm/exynos: Convert to generic image format library
> > > > drm/i915: Convert to generic image format library
> > > > drm/ipuv3: Convert to generic image format library
> > > > drm/msm: Convert to generic image format library
> > > > drm/omap: Convert to generic image format library
> > > > drm/rockchip: Convert to generic image format library
> > > > drm/tegra: Convert to generic image format library
> > > > drm/fourcc: Remove old DRM format API
> > > > lib: image-formats: Add v4l2 formats support
> > > > lib: image-formats: Add more functions
> > > > media: sun6i: Convert to the image format API
> > >
> > > In the interest of making myself unpopular: Why move this out of drm?
> > >
> > > We do have a bunch of other such shared helpers already (mostly in
> > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > sure that's going better than keeping it maintained in drm.
> > >
> > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > dropping the drm prefix isn't going to help I think.
> > >
> > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > use it without dragging in all of drm), and we need to add some fields for
> > > converting to v4l fourcc codes (which are different). But that should be
> > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > it's actually a feature: It makes it really clear that these are the drm
> > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > that. That allocation authority is also already baked into various khr/ext
> > > standards, too.
> >
> > The way I see it, there's a fundamental difference between the UAPI
> > and the kernel. I don't suggest we change anything about the UAPI: the
> > drm formats should keep their prefix, drm_fourcc.h can remain that
> > authority, it's all fine.
> >
> > Internally however, the long term goal is to share the fourcc's
> > between DRM and V4L2 for the same formats. It basically means that of
> > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > exists in v4l2 but not DRM, and that is far more likely, given the
> > already extensive v4l2 formats support.
>
> Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> format identifier space.

No to what exactly?

> And a lot of people pushed for the "fourcc is a standard", when
> really it's totally not.

Even if it's not a standard, having consistency would be a good thing.

And you said yourself that DRM fourcc is now pretty much an authority
for the fourcc, so it definitely looks like a standard to me.

> v4l tends to conflate pixel format with stuff that we tend to encode
> in modifiers a lot more.

Boris is working on adding the modifiers concept to v4l2, so we're
converging here, and we can totally have a layer in v4l2 to convert
between old v4l2 "format+modifiers" formats, and DRM style formats.

> There's a bunch of reasons we can't just use v4l, and they're as
> valid as ever:
>
> - We overlap badly in some areas, so even if fourcc codes match, we
> can't use them and need a duplicated DRM_FOURCC code.

Do yo have an example of one of those areas?

> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> e.g. offset for planar yuv formats, or tiling mode

As I was saying, this changes on the v4l2 side, and converging to
what DRM is doing.

> - drm fourcc code doesn't actually define the drm_format_info
> uniquely, drivers can override that (that's an explicit design
> intent of modifiers, to allow drivers to add another plane for
> e.g. compression information). You'd need to pull that driver
> knowledge into your format library.

I'm not sure how my patches are changing anything here. This is
litterally the same code, with the functions renamed.

If drivers want to override that, then yeah, fine, we can let them do
that. Just like any helper this just provides a default that covers
most of the cases.

> Iow there's no way we can easily adopt v4l fourcc, except if we do
> something like a new addfb flag.

For the formats that would be described as a modifier, sure. For all
the others (that are not yet supported by DRM), then I don't really
see why not.

> > And given how the current state is a mess in this regard, I'm not too
> > optimistic about keeping the formats in their relevant frameworks.
> >
> > Having a shared library, governed by both, will make this far easier,
> > since it will be easy to discover the formats that are already
> > supported by the other subsystem.
>
> I think a compat library that (tries to, best effort) convert between
> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> to the conversion functions for videomode <-> drm_display_mode
> perhaps. That should be useful for drivers.

That's not really what this series is about though. That series is
about sharing the (image|pixels) formats database across everyone so
that everyone can benefit from it.

> Unifying the formats themselves, and all the associated metadata is
> imo a no-go, and was a pretty conscious decision when we implemented
> drm_fourcc a few years back.
>
> > If we want to keep the current library in DRM, we have two options
> > then:
> >
> > - Support all the v4l2 formats in the DRM library, which is
> > essentially what I'm doing in the last patches. However, that
> > would require to have the v4l2 developpers also reviewing stuff
> > there. And given how busy they are, I cannot really see how that
> > would work.
>
> Well, if we end up with a common library then yes we need cross
> review. There's no way around that. Doesn't matter where exactly that
> library is in the filesystem tree, and adding a special MAINTAINERS
> entry for anything related to fourcc (both drm and v4l) to make sure
> they get cross-posted is easy. No file renaming needed.

That would create some governing issues as well. For example, if you
ever have a patch from one fourcc addition (that might or might not be
covered by v4l2), will you wait for any v4l2 developper to review it?

If it's shared code, then it should be shared, and every client
framework put on an equal footing.

> > - Develop the same library from within v4l2. That is really a poor
> > solution, since the information would be greatly duplicated
> > between the two, and in terms of maintainance, code, and binary
> > size that would be duplicated too.
>
> It's essentially what we decided to do for drm years back.

And it was probably the right solution back then, but I'm really not
convinced it's still the right thing to do today.

> > Having it shared allows to easily share, and discover formats from the
> > other subsystem, and to have a single, unique place where this is
> > centralized.
>
> What I think could work as middle ground:
> - Put drm_format stuff into a separate .ko
> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> posted to both drm and v4l lists. Easy on the drm side, since it's all
> separate files. Not sure it's so convenient for v4l uapi.
> - Add a conversion library that tries to best-effort map between drm
> and v4l formats. On the drm side that most likely means you need
> offsets for planes, and modifiers too (since those are implied in some
> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> the drivers that use this library need.
> - Add drm_fourcc as-needed by these drivers that want to use a unified
> format space.
>
> Forcing this unification on everyone otoh is imo way too much.

v4l2 is starting to converge with DRM, and we're using the DRM API
pretty much untouched for that library, so I'm not really sure how
anyone is hurt by that unification.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (10.40 kB)
signature.asc (235.00 B)
Download all attachments

2019-04-18 10:12:35

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard
<[email protected]> wrote:
>
> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard <[email protected]> wrote:
> > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > Hi,
> > > > >
> > > > > DRM comes with an extensive format support to retrieve the various
> > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > development.
> > > > >
> > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > by that particular driver. This leads to a lot of duplication and
> > > > > boilerplate code in the v4l2 drivers.
> > > > >
> > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > used.
> > > > >
> > > > > Let me know what you think,
> > > > > Maxime
> > > > >
> > > > > Changes from RFC:
> > > > > - Rebased on next
> > > > > - Fixed the various formats mapping
> > > > > - Added tags
> > > > > - Did most of the formats functions as inline functions
> > > > > - Used a consistent prefix for all the utilities functions
> > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > arm64 and x86_64
> > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > functions
> > > > > - Added License and copyright headers on missing files
> > > > >
> > > > > Maxime Ripard (20):
> > > > > drm: Remove users of drm_format_num_planes
> > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > lib: Add video format information library
> > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > drm/malidp: Convert to generic image format library
> > > > > drm/client: Convert to generic image format library
> > > > > drm/exynos: Convert to generic image format library
> > > > > drm/i915: Convert to generic image format library
> > > > > drm/ipuv3: Convert to generic image format library
> > > > > drm/msm: Convert to generic image format library
> > > > > drm/omap: Convert to generic image format library
> > > > > drm/rockchip: Convert to generic image format library
> > > > > drm/tegra: Convert to generic image format library
> > > > > drm/fourcc: Remove old DRM format API
> > > > > lib: image-formats: Add v4l2 formats support
> > > > > lib: image-formats: Add more functions
> > > > > media: sun6i: Convert to the image format API
> > > >
> > > > In the interest of making myself unpopular: Why move this out of drm?
> > > >
> > > > We do have a bunch of other such shared helpers already (mostly in
> > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > sure that's going better than keeping it maintained in drm.
> > > >
> > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > dropping the drm prefix isn't going to help I think.
> > > >
> > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > use it without dragging in all of drm), and we need to add some fields for
> > > > converting to v4l fourcc codes (which are different). But that should be
> > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > it's actually a feature: It makes it really clear that these are the drm
> > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > that. That allocation authority is also already baked into various khr/ext
> > > > standards, too.
> > >
> > > The way I see it, there's a fundamental difference between the UAPI
> > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > authority, it's all fine.
> > >
> > > Internally however, the long term goal is to share the fourcc's
> > > between DRM and V4L2 for the same formats. It basically means that of
> > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > already extensive v4l2 formats support.
> >
> > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > format identifier space.
>
> No to what exactly?
>
> > And a lot of people pushed for the "fourcc is a standard", when
> > really it's totally not.
>
> Even if it's not a standard, having consistency would be a good thing.
>
> And you said yourself that DRM fourcc is now pretty much an authority
> for the fourcc, so it definitely looks like a standard to me.

drm fourcc is the authority for drm fourcc codes. Not for any of the
others (and there's lots of them). Now it's used in a bunch of other
places (khr standards, dri protocols in wayland/X11), but they're
still only drm fourcc. There is no overall fourcc standard.

> > v4l tends to conflate pixel format with stuff that we tend to encode
> > in modifiers a lot more.
>
> Boris is working on adding the modifiers concept to v4l2, so we're
> converging here, and we can totally have a layer in v4l2 to convert
> between old v4l2 "format+modifiers" formats, and DRM style formats.
>
> > There's a bunch of reasons we can't just use v4l, and they're as
> > valid as ever:
> >
> > - We overlap badly in some areas, so even if fourcc codes match, we
> > can't use them and need a duplicated DRM_FOURCC code.
>
> Do yo have an example of one of those areas?

I think the rgb stuff was one of the big reasons to not reuse any
existing fourcc standard (whether v4l, or another one from e.g. video
container formats). We had initial patches to reuse the fourcc that
existed, but the end result was really inconsistent, so we ditch that
and rolled out a new set of entirely drm specific fourcc codes for
rgba.

> > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > e.g. offset for planar yuv formats, or tiling mode
>
> As I was saying, this changes on the v4l2 side, and converging to
> what DRM is doing.
>
> > - drm fourcc code doesn't actually define the drm_format_info
> > uniquely, drivers can override that (that's an explicit design
> > intent of modifiers, to allow drivers to add another plane for
> > e.g. compression information). You'd need to pull that driver
> > knowledge into your format library.
>
> I'm not sure how my patches are changing anything here. This is
> litterally the same code, with the functions renamed.
>
> If drivers want to override that, then yeah, fine, we can let them do
> that. Just like any helper this just provides a default that covers
> most of the cases.
>
> > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > something like a new addfb flag.
>
> For the formats that would be described as a modifier, sure. For all
> the others (that are not yet supported by DRM), then I don't really
> see why not.

See above, we tried that initially, didn't pass the ocd tests when
reviewing. Maybe the situation is better outside of rbgx/a formats,
and I think we do at least try to use the same fourcc codes there when
there already is one. But then the details occasionally look
different.

> > > And given how the current state is a mess in this regard, I'm not too
> > > optimistic about keeping the formats in their relevant frameworks.
> > >
> > > Having a shared library, governed by both, will make this far easier,
> > > since it will be easy to discover the formats that are already
> > > supported by the other subsystem.
> >
> > I think a compat library that (tries to, best effort) convert between
> > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > to the conversion functions for videomode <-> drm_display_mode
> > perhaps. That should be useful for drivers.
>
> That's not really what this series is about though. That series is
> about sharing the (image|pixels) formats database across everyone so
> that everyone can benefit from it.

Yeah I know. I still think leaving the drm fourcc with the drm prefix
would be good, since there's really no standard here.

> > Unifying the formats themselves, and all the associated metadata is
> > imo a no-go, and was a pretty conscious decision when we implemented
> > drm_fourcc a few years back.
> >
> > > If we want to keep the current library in DRM, we have two options
> > > then:
> > >
> > > - Support all the v4l2 formats in the DRM library, which is
> > > essentially what I'm doing in the last patches. However, that
> > > would require to have the v4l2 developpers also reviewing stuff
> > > there. And given how busy they are, I cannot really see how that
> > > would work.
> >
> > Well, if we end up with a common library then yes we need cross
> > review. There's no way around that. Doesn't matter where exactly that
> > library is in the filesystem tree, and adding a special MAINTAINERS
> > entry for anything related to fourcc (both drm and v4l) to make sure
> > they get cross-posted is easy. No file renaming needed.
>
> That would create some governing issues as well. For example, if you
> ever have a patch from one fourcc addition (that might or might not be
> covered by v4l2), will you wait for any v4l2 developper to review it?

None of this is fixed by code renaming or locations. Either way we
need to figure that out.

And yes part of the reasons for not moving this out of drm is that I'm
not a fan of boutique trees for small stuff. If sharing means we need
to split the drm_fourcc code and library out of drm trees, I'm not
sure that's a good idea. We're already super liberal with merging
anything through driver trees with acks, and integrating them quickly
into drm-next. This would still be workable if v4l sends regular pull
requests to drm-next (every 1-2 weeks, like the other big gpu trees
do). If we can only sync up once per merge window with a shared
boutique tree for formats only, life is going to be painful.

> If it's shared code, then it should be shared, and every client
> framework put on an equal footing.
>
> > > - Develop the same library from within v4l2. That is really a poor
> > > solution, since the information would be greatly duplicated
> > > between the two, and in terms of maintainance, code, and binary
> > > size that would be duplicated too.
> >
> > It's essentially what we decided to do for drm years back.
>
> And it was probably the right solution back then, but I'm really not
> convinced it's still the right thing to do today.
>
> > > Having it shared allows to easily share, and discover formats from the
> > > other subsystem, and to have a single, unique place where this is
> > > centralized.
> >
> > What I think could work as middle ground:
> > - Put drm_format stuff into a separate .ko
> > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > separate files. Not sure it's so convenient for v4l uapi.
> > - Add a conversion library that tries to best-effort map between drm
> > and v4l formats. On the drm side that most likely means you need
> > offsets for planes, and modifiers too (since those are implied in some
> > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > the drivers that use this library need.
> > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > format space.
> >
> > Forcing this unification on everyone otoh is imo way too much.
>
> v4l2 is starting to converge with DRM, and we're using the DRM API
> pretty much untouched for that library, so I'm not really sure how
> anyone is hurt by that unification.

It might make sense to regularly pull v4l updates into drm-next then
anyway. That would also remove the need to have the format library
somewhere else.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-04-18 11:51:51

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > And a lot of people pushed for the "fourcc is a standard", when
> > really it's totally not.
>
> Even if it's not a standard, having consistency would be a good thing.
>
> And you said yourself that DRM fourcc is now pretty much an authority
> for the fourcc, so it definitely looks like a standard to me.

I think trying to make the V4L2 and DRM fourccs converge is a lost
cause, as it has already significantly diverged. Even if we coordinate
an effort to introduce new formats with the same fourcc on both sides,
I don't see what good that would be since the formats we have now are
still plagued by the inconsistency.

I think we always need an explicit translation step from either v4l2 or
drm to the internal representation and back, without ever assuming that
formats might be compatible because they share the same fourcc.

It looks like so far, V4L2 pixel formats describe a DRM pixel format +
modifier. I think Boris (CCed) is working to change that by allowing to
pass a DRM modifier through V4L2. With that, we'd be in a situation
where some formats are described by the v4l2 pixfmt alone and some
formats are also described a modifier (but I looked at it from a
distance so might have misunderstod). That feels better since it avoids
the combinatory explosion from describing each format + modifier
individually.

What do you think?

Cheers,

Paul

> > v4l tends to conflate pixel format with stuff that we tend to encode
> > in modifiers a lot more.
>
> Boris is working on adding the modifiers concept to v4l2, so we're
> converging here, and we can totally have a layer in v4l2 to convert
> between old v4l2 "format+modifiers" formats, and DRM style formats.
>
> > There's a bunch of reasons we can't just use v4l, and they're as
> > valid as ever:
> >
> > - We overlap badly in some areas, so even if fourcc codes match, we
> > can't use them and need a duplicated DRM_FOURCC code.
>
> Do yo have an example of one of those areas?
>
> > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > e.g. offset for planar yuv formats, or tiling mode
>
> As I was saying, this changes on the v4l2 side, and converging to
> what DRM is doing.
>
> > - drm fourcc code doesn't actually define the drm_format_info
> > uniquely, drivers can override that (that's an explicit design
> > intent of modifiers, to allow drivers to add another plane for
> > e.g. compression information). You'd need to pull that driver
> > knowledge into your format library.
>
> I'm not sure how my patches are changing anything here. This is
> litterally the same code, with the functions renamed.
>
> If drivers want to override that, then yeah, fine, we can let them do
> that. Just like any helper this just provides a default that covers
> most of the cases.
>
> > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > something like a new addfb flag.
>
> For the formats that would be described as a modifier, sure. For all
> the others (that are not yet supported by DRM), then I don't really
> see why not.
>
> > > And given how the current state is a mess in this regard, I'm not too
> > > optimistic about keeping the formats in their relevant frameworks.
> > >
> > > Having a shared library, governed by both, will make this far easier,
> > > since it will be easy to discover the formats that are already
> > > supported by the other subsystem.
> >
> > I think a compat library that (tries to, best effort) convert between
> > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > to the conversion functions for videomode <-> drm_display_mode
> > perhaps. That should be useful for drivers.
>
> That's not really what this series is about though. That series is
> about sharing the (image|pixels) formats database across everyone so
> that everyone can benefit from it.
>
> > Unifying the formats themselves, and all the associated metadata is
> > imo a no-go, and was a pretty conscious decision when we implemented
> > drm_fourcc a few years back.
> >
> > > If we want to keep the current library in DRM, we have two options
> > > then:
> > >
> > > - Support all the v4l2 formats in the DRM library, which is
> > > essentially what I'm doing in the last patches. However, that
> > > would require to have the v4l2 developpers also reviewing stuff
> > > there. And given how busy they are, I cannot really see how that
> > > would work.
> >
> > Well, if we end up with a common library then yes we need cross
> > review. There's no way around that. Doesn't matter where exactly that
> > library is in the filesystem tree, and adding a special MAINTAINERS
> > entry for anything related to fourcc (both drm and v4l) to make sure
> > they get cross-posted is easy. No file renaming needed.
>
> That would create some governing issues as well. For example, if you
> ever have a patch from one fourcc addition (that might or might not be
> covered by v4l2), will you wait for any v4l2 developper to review it?
>
> If it's shared code, then it should be shared, and every client
> framework put on an equal footing.
>
> > > - Develop the same library from within v4l2. That is really a poor
> > > solution, since the information would be greatly duplicated
> > > between the two, and in terms of maintainance, code, and binary
> > > size that would be duplicated too.
> >
> > It's essentially what we decided to do for drm years back.
>
> And it was probably the right solution back then, but I'm really not
> convinced it's still the right thing to do today.
>
> > > Having it shared allows to easily share, and discover formats from the
> > > other subsystem, and to have a single, unique place where this is
> > > centralized.
> >
> > What I think could work as middle ground:
> > - Put drm_format stuff into a separate .ko
> > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > separate files. Not sure it's so convenient for v4l uapi.
> > - Add a conversion library that tries to best-effort map between drm
> > and v4l formats. On the drm side that most likely means you need
> > offsets for planes, and modifiers too (since those are implied in some
> > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > the drivers that use this library need.
> > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > format space.
> >
> > Forcing this unification on everyone otoh is imo way too much.
>
> v4l2 is starting to converge with DRM, and we're using the DRM API
> pretty much untouched for that library, so I'm not really sure how
> anyone is hurt by that unification.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-18 12:03:23

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard
> <[email protected]> wrote:
> >
> > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard <[email protected]> wrote:
> > > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > > Hi,
> > > > > >
> > > > > > DRM comes with an extensive format support to retrieve the various
> > > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > > development.
> > > > > >
> > > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > > by that particular driver. This leads to a lot of duplication and
> > > > > > boilerplate code in the v4l2 drivers.
> > > > > >
> > > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > > used.
> > > > > >
> > > > > > Let me know what you think,
> > > > > > Maxime
> > > > > >
> > > > > > Changes from RFC:
> > > > > > - Rebased on next
> > > > > > - Fixed the various formats mapping
> > > > > > - Added tags
> > > > > > - Did most of the formats functions as inline functions
> > > > > > - Used a consistent prefix for all the utilities functions
> > > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > > arm64 and x86_64
> > > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > > functions
> > > > > > - Added License and copyright headers on missing files
> > > > > >
> > > > > > Maxime Ripard (20):
> > > > > > drm: Remove users of drm_format_num_planes
> > > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > > lib: Add video format information library
> > > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > > drm/malidp: Convert to generic image format library
> > > > > > drm/client: Convert to generic image format library
> > > > > > drm/exynos: Convert to generic image format library
> > > > > > drm/i915: Convert to generic image format library
> > > > > > drm/ipuv3: Convert to generic image format library
> > > > > > drm/msm: Convert to generic image format library
> > > > > > drm/omap: Convert to generic image format library
> > > > > > drm/rockchip: Convert to generic image format library
> > > > > > drm/tegra: Convert to generic image format library
> > > > > > drm/fourcc: Remove old DRM format API
> > > > > > lib: image-formats: Add v4l2 formats support
> > > > > > lib: image-formats: Add more functions
> > > > > > media: sun6i: Convert to the image format API
> > > > >
> > > > > In the interest of making myself unpopular: Why move this out of drm?
> > > > >
> > > > > We do have a bunch of other such shared helpers already (mostly in
> > > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > > sure that's going better than keeping it maintained in drm.
> > > > >
> > > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > > dropping the drm prefix isn't going to help I think.
> > > > >
> > > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > > use it without dragging in all of drm), and we need to add some fields for
> > > > > converting to v4l fourcc codes (which are different). But that should be
> > > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > > it's actually a feature: It makes it really clear that these are the drm
> > > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > > that. That allocation authority is also already baked into various khr/ext
> > > > > standards, too.
> > > >
> > > > The way I see it, there's a fundamental difference between the UAPI
> > > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > > authority, it's all fine.
> > > >
> > > > Internally however, the long term goal is to share the fourcc's
> > > > between DRM and V4L2 for the same formats. It basically means that of
> > > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > > already extensive v4l2 formats support.
> > >
> > > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > > format identifier space.
> >
> > No to what exactly?
> >
> > > And a lot of people pushed for the "fourcc is a standard", when
> > > really it's totally not.
> >
> > Even if it's not a standard, having consistency would be a good thing.
> >
> > And you said yourself that DRM fourcc is now pretty much an authority
> > for the fourcc, so it definitely looks like a standard to me.
>
> drm fourcc is the authority for drm fourcc codes. Not for any of the
> others (and there's lots of them). Now it's used in a bunch of other
> places (khr standards, dri protocols in wayland/X11), but they're
> still only drm fourcc. There is no overall fourcc standard.

Sounds like a de-facto standard to me ¯\_(ツ)_/¯

But even then, whether we decide to converge the fourcc or not, that's
still the long term goal. Short term, that series doesn't do any of
it, it just makes it easier if we ever want to go down that road.

> > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > in modifiers a lot more.
> >
> > Boris is working on adding the modifiers concept to v4l2, so we're
> > converging here, and we can totally have a layer in v4l2 to convert
> > between old v4l2 "format+modifiers" formats, and DRM style formats.
> >
> > > There's a bunch of reasons we can't just use v4l, and they're as
> > > valid as ever:
> > >
> > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > can't use them and need a duplicated DRM_FOURCC code.
> >
> > Do yo have an example of one of those areas?
>
> I think the rgb stuff was one of the big reasons to not reuse any
> existing fourcc standard (whether v4l, or another one from e.g. video
> container formats). We had initial patches to reuse the fourcc that
> existed, but the end result was really inconsistent, so we ditch that
> and rolled out a new set of entirely drm specific fourcc codes for
> rgba.

Ok, so let's ditch that plan and focus on the rest

> > > > And given how the current state is a mess in this regard, I'm not too
> > > > optimistic about keeping the formats in their relevant frameworks.
> > > >
> > > > Having a shared library, governed by both, will make this far easier,
> > > > since it will be easy to discover the formats that are already
> > > > supported by the other subsystem.
> > >
> > > I think a compat library that (tries to, best effort) convert between
> > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > to the conversion functions for videomode <-> drm_display_mode
> > > perhaps. That should be useful for drivers.
> >
> > That's not really what this series is about though. That series is
> > about sharing the (image|pixels) formats database across everyone so
> > that everyone can benefit from it.
>
> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> would be good, since there's really no standard here.
>
> > > Unifying the formats themselves, and all the associated metadata is
> > > imo a no-go, and was a pretty conscious decision when we implemented
> > > drm_fourcc a few years back.
> > >
> > > > If we want to keep the current library in DRM, we have two options
> > > > then:
> > > >
> > > > - Support all the v4l2 formats in the DRM library, which is
> > > > essentially what I'm doing in the last patches. However, that
> > > > would require to have the v4l2 developpers also reviewing stuff
> > > > there. And given how busy they are, I cannot really see how that
> > > > would work.
> > >
> > > Well, if we end up with a common library then yes we need cross
> > > review. There's no way around that. Doesn't matter where exactly that
> > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > they get cross-posted is easy. No file renaming needed.
> >
> > That would create some governing issues as well. For example, if you
> > ever have a patch from one fourcc addition (that might or might not be
> > covered by v4l2), will you wait for any v4l2 developper to review it?
>
> None of this is fixed by code renaming or locations. Either way we
> need to figure that out.
>
> And yes part of the reasons for not moving this out of drm is that I'm
> not a fan of boutique trees for small stuff. If sharing means we need
> to split the drm_fourcc code and library out of drm trees, I'm not
> sure that's a good idea. We're already super liberal with merging
> anything through driver trees with acks, and integrating them quickly
> into drm-next. This would still be workable if v4l sends regular pull
> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> do). If we can only sync up once per merge window with a shared
> boutique tree for formats only, life is going to be painful.

I don't get why we want to turn DRM into some kind of a black hole
that would pull everything. We don't have to, really. And at the same
time it carries the message that v4l2 is less important than DRM for
some reason, which I'm really not comfortable with.

And I don't really get why you're against this in the first
place. When you have some code in a single driver that would benefit
more driver, you create a helper and move it into the core.

In this case, we have some code used by a framework that more
framework could use, and we move it to a core-er place. How is that
different?

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (10.83 kB)
signature.asc (235.00 B)
Download all attachments

2019-04-18 12:35:39

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 2:01 PM Maxime Ripard <[email protected]> wrote:
> On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> > On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard
> > <[email protected]> wrote:
> > >
> > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard <[email protected]> wrote:
> > > > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > > > Hi,
> > > > > > >
> > > > > > > DRM comes with an extensive format support to retrieve the various
> > > > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > > > development.
> > > > > > >
> > > > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > > > by that particular driver. This leads to a lot of duplication and
> > > > > > > boilerplate code in the v4l2 drivers.
> > > > > > >
> > > > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > > > used.
> > > > > > >
> > > > > > > Let me know what you think,
> > > > > > > Maxime
> > > > > > >
> > > > > > > Changes from RFC:
> > > > > > > - Rebased on next
> > > > > > > - Fixed the various formats mapping
> > > > > > > - Added tags
> > > > > > > - Did most of the formats functions as inline functions
> > > > > > > - Used a consistent prefix for all the utilities functions
> > > > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > > > arm64 and x86_64
> > > > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > > > functions
> > > > > > > - Added License and copyright headers on missing files
> > > > > > >
> > > > > > > Maxime Ripard (20):
> > > > > > > drm: Remove users of drm_format_num_planes
> > > > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > > > lib: Add video format information library
> > > > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > > > drm/malidp: Convert to generic image format library
> > > > > > > drm/client: Convert to generic image format library
> > > > > > > drm/exynos: Convert to generic image format library
> > > > > > > drm/i915: Convert to generic image format library
> > > > > > > drm/ipuv3: Convert to generic image format library
> > > > > > > drm/msm: Convert to generic image format library
> > > > > > > drm/omap: Convert to generic image format library
> > > > > > > drm/rockchip: Convert to generic image format library
> > > > > > > drm/tegra: Convert to generic image format library
> > > > > > > drm/fourcc: Remove old DRM format API
> > > > > > > lib: image-formats: Add v4l2 formats support
> > > > > > > lib: image-formats: Add more functions
> > > > > > > media: sun6i: Convert to the image format API
> > > > > >
> > > > > > In the interest of making myself unpopular: Why move this out of drm?
> > > > > >
> > > > > > We do have a bunch of other such shared helpers already (mostly in
> > > > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > > > sure that's going better than keeping it maintained in drm.
> > > > > >
> > > > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > > > dropping the drm prefix isn't going to help I think.
> > > > > >
> > > > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > > > use it without dragging in all of drm), and we need to add some fields for
> > > > > > converting to v4l fourcc codes (which are different). But that should be
> > > > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > > > it's actually a feature: It makes it really clear that these are the drm
> > > > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > > > that. That allocation authority is also already baked into various khr/ext
> > > > > > standards, too.
> > > > >
> > > > > The way I see it, there's a fundamental difference between the UAPI
> > > > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > > > authority, it's all fine.
> > > > >
> > > > > Internally however, the long term goal is to share the fourcc's
> > > > > between DRM and V4L2 for the same formats. It basically means that of
> > > > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > > > already extensive v4l2 formats support.
> > > >
> > > > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > > > format identifier space.
> > >
> > > No to what exactly?
> > >
> > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > really it's totally not.
> > >
> > > Even if it's not a standard, having consistency would be a good thing.
> > >
> > > And you said yourself that DRM fourcc is now pretty much an authority
> > > for the fourcc, so it definitely looks like a standard to me.
> >
> > drm fourcc is the authority for drm fourcc codes. Not for any of the
> > others (and there's lots of them). Now it's used in a bunch of other
> > places (khr standards, dri protocols in wayland/X11), but they're
> > still only drm fourcc. There is no overall fourcc standard.
>
> Sounds like a de-facto standard to me ¯\_(ツ)_/¯
>
> But even then, whether we decide to converge the fourcc or not, that's
> still the long term goal. Short term, that series doesn't do any of
> it, it just makes it easier if we ever want to go down that road.
>
> > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > in modifiers a lot more.
> > >
> > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > converging here, and we can totally have a layer in v4l2 to convert
> > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > >
> > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > valid as ever:
> > > >
> > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > can't use them and need a duplicated DRM_FOURCC code.
> > >
> > > Do yo have an example of one of those areas?
> >
> > I think the rgb stuff was one of the big reasons to not reuse any
> > existing fourcc standard (whether v4l, or another one from e.g. video
> > container formats). We had initial patches to reuse the fourcc that
> > existed, but the end result was really inconsistent, so we ditch that
> > and rolled out a new set of entirely drm specific fourcc codes for
> > rgba.
>
> Ok, so let's ditch that plan and focus on the rest
>
> > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > >
> > > > > Having a shared library, governed by both, will make this far easier,
> > > > > since it will be easy to discover the formats that are already
> > > > > supported by the other subsystem.
> > > >
> > > > I think a compat library that (tries to, best effort) convert between
> > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > to the conversion functions for videomode <-> drm_display_mode
> > > > perhaps. That should be useful for drivers.
> > >
> > > That's not really what this series is about though. That series is
> > > about sharing the (image|pixels) formats database across everyone so
> > > that everyone can benefit from it.
> >
> > Yeah I know. I still think leaving the drm fourcc with the drm prefix
> > would be good, since there's really no standard here.
> >
> > > > Unifying the formats themselves, and all the associated metadata is
> > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > drm_fourcc a few years back.
> > > >
> > > > > If we want to keep the current library in DRM, we have two options
> > > > > then:
> > > > >
> > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > essentially what I'm doing in the last patches. However, that
> > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > there. And given how busy they are, I cannot really see how that
> > > > > would work.
> > > >
> > > > Well, if we end up with a common library then yes we need cross
> > > > review. There's no way around that. Doesn't matter where exactly that
> > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > they get cross-posted is easy. No file renaming needed.
> > >
> > > That would create some governing issues as well. For example, if you
> > > ever have a patch from one fourcc addition (that might or might not be
> > > covered by v4l2), will you wait for any v4l2 developper to review it?
> >
> > None of this is fixed by code renaming or locations. Either way we
> > need to figure that out.
> >
> > And yes part of the reasons for not moving this out of drm is that I'm
> > not a fan of boutique trees for small stuff. If sharing means we need
> > to split the drm_fourcc code and library out of drm trees, I'm not
> > sure that's a good idea. We're already super liberal with merging
> > anything through driver trees with acks, and integrating them quickly
> > into drm-next. This would still be workable if v4l sends regular pull
> > requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > do). If we can only sync up once per merge window with a shared
> > boutique tree for formats only, life is going to be painful.
>
> I don't get why we want to turn DRM into some kind of a black hole
> that would pull everything. We don't have to, really. And at the same
> time it carries the message that v4l2 is less important than DRM for
> some reason, which I'm really not comfortable with.

Make another tree somewhere that pulls in trees more often than every
merge window, and I'm happy. It's the coordination effort of lots of
trees that creates the black hole, not the other way round. Yes topic
trees work, but if topic trees are persistent something with the
organization of trees is wrong and needs to change. This very much
looks like we'll end up with a perpetual topic branch for format stuff
between drm and v4l.

The other shared stuff (like hdmi infoframes) seems to change a lot
less often, so the occasional patch hasn't been a pain. But drm_fourcc
related stuff sees a lot of work, both in adding new formats and in
refactoring the library to keep up with all the new use-cases.

And yes I think an overall gfx-like-stuff.git tree for drm and v4l and
the few other bits really makes tons of sense. Not as a tree where
people commit, but as the 2nd-level integration tree (like drm.git
right now for gpu stuff).

> And I don't really get why you're against this in the first
> place. When you have some code in a single driver that would benefit
> more driver, you create a helper and move it into the core.

It's a feature that drm doesn't share that much code with other parts
of the kernel, it makes backporting the gfx stack to lts kernels a lot
easier. Until someone fixes the upstream kernel release model to no
longer need large scale gpu driver backports, we need to keep that.

> In this case, we have some code used by a framework that more
> framework could use, and we move it to a core-er place. How is that
> different?

Imo core sharing for code sharing's sake is overrated. If we already
have drm and v4l tightly integrated as a community, then code sharing
becomes a lot easier, and a lot more reasonable to do. Plus we can
then just stuff code int drivers/gpu or drivers/video (or merge these
two because really it's all the same). But my understanding is that
integrating more tightly with the drm folks is a very contreversial
topic in v4l, and until that's resolved I don't see a huge need or
benefit in sharing tons of code. And the format stuff is a lot more
central to kms than e.g. the infoframe helpers.

Au contraire, I think forcing this has a lot of potential for needless
fights between drm and v4l. Hence my suggestion to try a minimal
format conversion library between the drm format world and the v4l
format wolrd, and see how that goes. That contains a lot less risk
than going all in right from the start.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-04-18 20:57:43

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Thu, Apr 18, 2019 at 02:32:14PM +0200, Daniel Vetter wrote:
> > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > drm_fourcc a few years back.
> > > > >
> > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > then:
> > > > > >
> > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > would work.
> > > > >
> > > > > Well, if we end up with a common library then yes we need cross
> > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > they get cross-posted is easy. No file renaming needed.
> > > >
> > > > That would create some governing issues as well. For example, if you
> > > > ever have a patch from one fourcc addition (that might or might not be
> > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > >
> > > None of this is fixed by code renaming or locations. Either way we
> > > need to figure that out.
> > >
> > > And yes part of the reasons for not moving this out of drm is that I'm
> > > not a fan of boutique trees for small stuff. If sharing means we need
> > > to split the drm_fourcc code and library out of drm trees, I'm not
> > > sure that's a good idea. We're already super liberal with merging
> > > anything through driver trees with acks, and integrating them quickly
> > > into drm-next. This would still be workable if v4l sends regular pull
> > > requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > > do). If we can only sync up once per merge window with a shared
> > > boutique tree for formats only, life is going to be painful.
> >
> > I don't get why we want to turn DRM into some kind of a black hole
> > that would pull everything. We don't have to, really. And at the same
> > time it carries the message that v4l2 is less important than DRM for
> > some reason, which I'm really not comfortable with.
>
> Make another tree somewhere that pulls in trees more often than every
> merge window, and I'm happy. It's the coordination effort of lots of
> trees that creates the black hole, not the other way round. Yes topic
> trees work, but if topic trees are persistent something with the
> organization of trees is wrong and needs to change. This very much
> looks like we'll end up with a perpetual topic branch for format stuff
> between drm and v4l.

Well, if v4l2 sends a PR to DRM every 1 or 2 weeks, that definitely
looks like a topic branch to me. And on a far more frequent basis than
when we will merge a format description.

> The other shared stuff (like hdmi infoframes) seems to change a lot
> less often, so the occasional patch hasn't been a pain. But drm_fourcc
> related stuff sees a lot of work, both in adding new formats and in
> refactoring the library to keep up with all the new use-cases.

When was the last time a refactoring that changed the API happened?

Most of the changes will be new format descriptions, and I guess that
would only concern a single tree.

And really, we're doing this all the time, so I'm not sure what the
big deal is here.

I feel like there's something that you don't really like about this,
but you're not saying this out loud.

Sure, the exact process needs to be figured out, and everyone needs to
agree upon that process. But that's pretty much it, and it's nothing
out of the ordinary.

> And yes I think an overall gfx-like-stuff.git tree for drm and v4l and
> the few other bits really makes tons of sense. Not as a tree where
> people commit, but as the 2nd-level integration tree (like drm.git
> right now for gpu stuff).
>
> > And I don't really get why you're against this in the first
> > place. When you have some code in a single driver that would benefit
> > more driver, you create a helper and move it into the core.
>
> It's a feature that drm doesn't share that much code with other parts
> of the kernel, it makes backporting the gfx stack to lts kernels a lot
> easier. Until someone fixes the upstream kernel release model to no
> longer need large scale gpu driver backports, we need to keep that.
>
> > In this case, we have some code used by a framework that more
> > framework could use, and we move it to a core-er place. How is that
> > different?
>
> Imo core sharing for code sharing's sake is overrated. If we already
> have drm and v4l tightly integrated as a community, then code sharing
> becomes a lot easier, and a lot more reasonable to do.

At least Laurent, Boris, Ezequiel, Gustavo and I have been working on
v4l2, so I'm not sure how not integrated we are.

> Plus we can then just stuff code int drivers/gpu or drivers/video
> (or merge these two because really it's all the same). But my
> understanding is that integrating more tightly with the drm folks is
> a very contreversial topic in v4l

So, I sent the RFC expecting that kind of feedback.

Hans replied mainly to that patch https://patchwork.freedesktop.org/patch/293043/

"
If we are creating a common library then I think we should change that rule
to: "unless they are in use by a DRM or V4L2 driver". And when new formats are
added, and they exists already for DRM or V4L2, then we should use the same
fourcc for the other subsystem.

I.e. if pixelformat V4L2_PIX_FMT_FOO was already defined, then add a:

#define DRM_FORMAT_FOO V4L2_PIX_FMT_FOO

rather than creating a new fourcc.

We could even start looking at redoing the whole scheme in a unified way, but
that's something for the (far) future.

This is already a big step forward.
"

So, not controversial at all.

> and until that's resolved I don't see a huge need or benefit in
> sharing tons of code.

That's mostly tons of data though. The code is pretty small and
trivial.

> And the format stuff is a lot more central to kms than e.g. the
> infoframe helpers.
>
> Au contraire, I think forcing this has a lot of potential for
> needless fights between drm and v4l.

We're all reasonable, so I'm not sure why we would need to fight here.

> Hence my suggestion to try a minimal format conversion library
> between the drm format world and the v4l format wolrd, and see how
> that goes. That contains a lot less risk than going all in right
> from the start.

And it's really not about getting access to the DRM fourcc. It's about
getting access to DRM's format description, so I'm not really sure
what there is to convert, we just want a lookup.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2019-04-20 23:08:29

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Paul,

On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> >> And a lot of people pushed for the "fourcc is a standard", when
> >> really it's totally not.
> >
> > Even if it's not a standard, having consistency would be a good thing.
> >
> > And you said yourself that DRM fourcc is now pretty much an authority
> > for the fourcc, so it definitely looks like a standard to me.
>
> I think trying to make the V4L2 and DRM fourccs converge is a lost
> cause, as it has already significantly diverged. Even if we coordinate
> an effort to introduce new formats with the same fourcc on both sides,
> I don't see what good that would be since the formats we have now are
> still plagued by the inconsistency.
>
> I think we always need an explicit translation step from either v4l2 or
> drm to the internal representation and back, without ever assuming that
> formats might be compatible because they share the same fourcc.

I don't agree. APIs evolve, and while we can't switch from one set of
4CCs to another in existing APIs, we could in new APIs. Boris is working
on new ioctls to handle formats in V4L2, and while 4CC unification could
be impopular from a userspace developers point of view there, I don't
think we have ruled it out completely. The move to the request API is
also an area where a common set of 4CCs could be used, as it will depart
from the existing V4L2 ioctls. To summarize my opinion, we're not there
yet, but I wouldn't rule it out completely for the future.

> It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> modifier.

DRM modifiers are mostly about tiling and compression, and we hardly
support these in V4L2. What are the modifiers you think are hardcoded in
4CCs in V4L2 ?

> I think Boris (CCed) is working to change that by allowing to
> pass a DRM modifier through V4L2. With that, we'd be in a situation
> where some formats are described by the v4l2 pixfmt alone and some
> formats are also described a modifier (but I looked at it from a
> distance so might have misunderstod). That feels better since it avoids
> the combinatory explosion from describing each format + modifier
> individually.
>
> What do you think?
>
> >> v4l tends to conflate pixel format with stuff that we tend to encode
> >> in modifiers a lot more.
> >
> > Boris is working on adding the modifiers concept to v4l2, so we're
> > converging here, and we can totally have a layer in v4l2 to convert
> > between old v4l2 "format+modifiers" formats, and DRM style formats.
> >
> >> There's a bunch of reasons we can't just use v4l, and they're as
> >> valid as ever:
> >>
> >> - We overlap badly in some areas, so even if fourcc codes match, we
> >> can't use them and need a duplicated DRM_FOURCC code.
> >
> > Do yo have an example of one of those areas?
> >
> >> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> >> e.g. offset for planar yuv formats, or tiling mode
> >
> > As I was saying, this changes on the v4l2 side, and converging to
> > what DRM is doing.
> >
> >> - drm fourcc code doesn't actually define the drm_format_info
> >> uniquely, drivers can override that (that's an explicit design
> >> intent of modifiers, to allow drivers to add another plane for
> >> e.g. compression information). You'd need to pull that driver
> >> knowledge into your format library.
> >
> > I'm not sure how my patches are changing anything here. This is
> > litterally the same code, with the functions renamed.
> >
> > If drivers want to override that, then yeah, fine, we can let them do
> > that. Just like any helper this just provides a default that covers
> > most of the cases.
> >
> >> Iow there's no way we can easily adopt v4l fourcc, except if we do
> >> something like a new addfb flag.
> >
> > For the formats that would be described as a modifier, sure. For all
> > the others (that are not yet supported by DRM), then I don't really
> > see why not.
> >
> >>> And given how the current state is a mess in this regard, I'm not too
> >>> optimistic about keeping the formats in their relevant frameworks.
> >>>
> >>> Having a shared library, governed by both, will make this far easier,
> >>> since it will be easy to discover the formats that are already
> >>> supported by the other subsystem.
> >>
> >> I think a compat library that (tries to, best effort) convert between
> >> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> >> to the conversion functions for videomode <-> drm_display_mode
> >> perhaps. That should be useful for drivers.
> >
> > That's not really what this series is about though. That series is
> > about sharing the (image|pixels) formats database across everyone so
> > that everyone can benefit from it.
> >
> >> Unifying the formats themselves, and all the associated metadata is
> >> imo a no-go, and was a pretty conscious decision when we implemented
> >> drm_fourcc a few years back.
> >>
> >>> If we want to keep the current library in DRM, we have two options
> >>> then:
> >>>
> >>> - Support all the v4l2 formats in the DRM library, which is
> >>> essentially what I'm doing in the last patches. However, that
> >>> would require to have the v4l2 developpers also reviewing stuff
> >>> there. And given how busy they are, I cannot really see how that
> >>> would work.
> >>
> >> Well, if we end up with a common library then yes we need cross
> >> review. There's no way around that. Doesn't matter where exactly that
> >> library is in the filesystem tree, and adding a special MAINTAINERS
> >> entry for anything related to fourcc (both drm and v4l) to make sure
> >> they get cross-posted is easy. No file renaming needed.
> >
> > That would create some governing issues as well. For example, if you
> > ever have a patch from one fourcc addition (that might or might not be
> > covered by v4l2), will you wait for any v4l2 developper to review it?
> >
> > If it's shared code, then it should be shared, and every client
> > framework put on an equal footing.
> >
> >>> - Develop the same library from within v4l2. That is really a poor
> >>> solution, since the information would be greatly duplicated
> >>> between the two, and in terms of maintainance, code, and binary
> >>> size that would be duplicated too.
> >>
> >> It's essentially what we decided to do for drm years back.
> >
> > And it was probably the right solution back then, but I'm really not
> > convinced it's still the right thing to do today.
> >
> >>> Having it shared allows to easily share, and discover formats from the
> >>> other subsystem, and to have a single, unique place where this is
> >>> centralized.
> >>
> >> What I think could work as middle ground:
> >> - Put drm_format stuff into a separate .ko
> >> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> >> posted to both drm and v4l lists. Easy on the drm side, since it's all
> >> separate files. Not sure it's so convenient for v4l uapi.
> >> - Add a conversion library that tries to best-effort map between drm
> >> and v4l formats. On the drm side that most likely means you need
> >> offsets for planes, and modifiers too (since those are implied in some
> >> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> >> the drivers that use this library need.
> >> - Add drm_fourcc as-needed by these drivers that want to use a unified
> >> format space.
> >>
> >> Forcing this unification on everyone otoh is imo way too much.
> >
> > v4l2 is starting to converge with DRM, and we're using the DRM API
> > pretty much untouched for that library, so I'm not really sure how
> > anyone is hurt by that unification.

--
Regards,

Laurent Pinchart

2019-04-20 23:08:29

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Daniel,

On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> > > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > > Hi,
> > > > > >
> > > > > > DRM comes with an extensive format support to retrieve the various
> > > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > > development.
> > > > > >
> > > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > > by that particular driver. This leads to a lot of duplication and
> > > > > > boilerplate code in the v4l2 drivers.
> > > > > >
> > > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > > used.
> > > > > >
> > > > > > Let me know what you think,
> > > > > > Maxime
> > > > > >
> > > > > > Changes from RFC:
> > > > > > - Rebased on next
> > > > > > - Fixed the various formats mapping
> > > > > > - Added tags
> > > > > > - Did most of the formats functions as inline functions
> > > > > > - Used a consistent prefix for all the utilities functions
> > > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > > arm64 and x86_64
> > > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > > functions
> > > > > > - Added License and copyright headers on missing files
> > > > > >
> > > > > > Maxime Ripard (20):
> > > > > > drm: Remove users of drm_format_num_planes
> > > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > > lib: Add video format information library
> > > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > > drm/malidp: Convert to generic image format library
> > > > > > drm/client: Convert to generic image format library
> > > > > > drm/exynos: Convert to generic image format library
> > > > > > drm/i915: Convert to generic image format library
> > > > > > drm/ipuv3: Convert to generic image format library
> > > > > > drm/msm: Convert to generic image format library
> > > > > > drm/omap: Convert to generic image format library
> > > > > > drm/rockchip: Convert to generic image format library
> > > > > > drm/tegra: Convert to generic image format library
> > > > > > drm/fourcc: Remove old DRM format API
> > > > > > lib: image-formats: Add v4l2 formats support
> > > > > > lib: image-formats: Add more functions
> > > > > > media: sun6i: Convert to the image format API
> > > > >
> > > > > In the interest of making myself unpopular: Why move this out of drm?
> > > > >
> > > > > We do have a bunch of other such shared helpers already (mostly in
> > > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > > sure that's going better than keeping it maintained in drm.

That's a bit of a different situation as both DRM and FBDEV address the
same features (display output), and FBDEV is deprecared and replaced by
DRM.

I'm not against maintaining a 4CC library in DRM (adding a third-party
maintainer would likely create more problems than it would solve), but
that doesn't mean the library has to live in drivers/gpu/, nor that it
needs to have the drm_ prefix. I would actually advocate to make it live
in a neutral directory, with a neutral prefix (kudos to anyone who can
propose a nice naming convention that would establish a new shared
ground for image/video-related Linux APIs), and maintained through the
DRM tree (possibly with extra entries in MAINTAINERS to ensure it
reaches all the related folks).

> > > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > > dropping the drm prefix isn't going to help I think.
> > > > >
> > > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > > use it without dragging in all of drm), and we need to add some fields for
> > > > > converting to v4l fourcc codes (which are different). But that should be
> > > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > > it's actually a feature: It makes it really clear that these are the drm
> > > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > > that. That allocation authority is also already baked into various khr/ext
> > > > > standards, too.

There's one thing that V4L2 has and DRM hasn't for 4CCs: good
documentation. Look at
https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
or
https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
for instance. It's painful to write, painful to read, but defines the
4CCs very clearly without ambiguity. I wouldn't be surprised if
different drivers used the same DRM 4CC for different formats due to the
lack of detailed documentation. Moving to a shared library for 4CCs
should also address the documentation side, and any new format added to
the kernel, whether from the V4L2 side or the DRM side, would be
required to provide detailed documentation. That would be a great
improvement for DRM 4CC handling.

> > > > The way I see it, there's a fundamental difference between the UAPI
> > > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > > authority, it's all fine.
> > > >
> > > > Internally however, the long term goal is to share the fourcc's
> > > > between DRM and V4L2 for the same formats. It basically means that of
> > > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > > already extensive v4l2 formats support.
> > >
> > > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > > format identifier space.
> >
> > No to what exactly?
> >
> > > And a lot of people pushed for the "fourcc is a standard", when
> > > really it's totally not.
> >
> > Even if it's not a standard, having consistency would be a good thing.
> >
> > And you said yourself that DRM fourcc is now pretty much an authority
> > for the fourcc, so it definitely looks like a standard to me.
>
> drm fourcc is the authority for drm fourcc codes. Not for any of the
> others (and there's lots of them). Now it's used in a bunch of other
> places (khr standards, dri protocols in wayland/X11), but they're
> still only drm fourcc. There is no overall fourcc standard.
>
> > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > in modifiers a lot more.
> >
> > Boris is working on adding the modifiers concept to v4l2, so we're
> > converging here, and we can totally have a layer in v4l2 to convert
> > between old v4l2 "format+modifiers" formats, and DRM style formats.
> >
> > > There's a bunch of reasons we can't just use v4l, and they're as
> > > valid as ever:
> > >
> > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > can't use them and need a duplicated DRM_FOURCC code.
> >
> > Do yo have an example of one of those areas?
>
> I think the rgb stuff was one of the big reasons to not reuse any
> existing fourcc standard (whether v4l, or another one from e.g. video
> container formats). We had initial patches to reuse the fourcc that
> existed, but the end result was really inconsistent, so we ditch that
> and rolled out a new set of entirely drm specific fourcc codes for
> rgba.

Could you give one or a couple of examples of V4L2 4CCs that are not
OCD-compatible ? :-)

> > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > e.g. offset for planar yuv formats, or tiling mode
> >
> > As I was saying, this changes on the v4l2 side, and converging to
> > what DRM is doing.
> >
> > > - drm fourcc code doesn't actually define the drm_format_info
> > > uniquely, drivers can override that (that's an explicit design
> > > intent of modifiers, to allow drivers to add another plane for
> > > e.g. compression information). You'd need to pull that driver
> > > knowledge into your format library.

That's a mistake in my opinion. We tried that in V4L2 to store metadata
in a separate plane, and had to go another route eventually as it
created a very bad mess.

There's a tendency in both subsystems to look at the other as a bit of a
retarded relative, and that's a shame, we have lots to learn from each
other's mistakes. That wouldn't be too difficult if people started
talking to each other.

A semi-related comment: DRM also carries other mistakes of its own, I'm
thinking about DRM_FORMAT_BIG_ENDIAN in particular

> > I'm not sure how my patches are changing anything here. This is
> > litterally the same code, with the functions renamed.
> >
> > If drivers want to override that, then yeah, fine, we can let them do
> > that. Just like any helper this just provides a default that covers
> > most of the cases.
> >
> > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > something like a new addfb flag.
> >
> > For the formats that would be described as a modifier, sure. For all
> > the others (that are not yet supported by DRM), then I don't really
> > see why not.
>
> See above, we tried that initially, didn't pass the ocd tests when
> reviewing. Maybe the situation is better outside of rbgx/a formats,
> and I think we do at least try to use the same fourcc codes there when
> there already is one. But then the details occasionally look
> different.
>
> > > > And given how the current state is a mess in this regard, I'm not too
> > > > optimistic about keeping the formats in their relevant frameworks.
> > > >
> > > > Having a shared library, governed by both, will make this far easier,
> > > > since it will be easy to discover the formats that are already
> > > > supported by the other subsystem.
> > >
> > > I think a compat library that (tries to, best effort) convert between
> > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > to the conversion functions for videomode <-> drm_display_mode
> > > perhaps. That should be useful for drivers.
> >
> > That's not really what this series is about though. That series is
> > about sharing the (image|pixels) formats database across everyone so
> > that everyone can benefit from it.
>
> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> would be good, since there's really no standard here.
>
> > > Unifying the formats themselves, and all the associated metadata is
> > > imo a no-go, and was a pretty conscious decision when we implemented
> > > drm_fourcc a few years back.
> > >
> > > > If we want to keep the current library in DRM, we have two options
> > > > then:
> > > >
> > > > - Support all the v4l2 formats in the DRM library, which is
> > > > essentially what I'm doing in the last patches. However, that
> > > > would require to have the v4l2 developpers also reviewing stuff
> > > > there. And given how busy they are, I cannot really see how that
> > > > would work.
> > >
> > > Well, if we end up with a common library then yes we need cross
> > > review. There's no way around that. Doesn't matter where exactly that
> > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > they get cross-posted is easy. No file renaming needed.
> >
> > That would create some governing issues as well. For example, if you
> > ever have a patch from one fourcc addition (that might or might not be
> > covered by v4l2), will you wait for any v4l2 developper to review it?
>
> None of this is fixed by code renaming or locations. Either way we
> need to figure that out.
>
> And yes part of the reasons for not moving this out of drm is that I'm
> not a fan of boutique trees for small stuff. If sharing means we need
> to split the drm_fourcc code and library out of drm trees, I'm not
> sure that's a good idea. We're already super liberal with merging
> anything through driver trees with acks, and integrating them quickly
> into drm-next. This would still be workable if v4l sends regular pull
> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> do). If we can only sync up once per merge window with a shared
> boutique tree for formats only, life is going to be painful.

That should be solved by the proposal above, maintaining the shared
library in the DRM tree. We would need to be careful there, and ideally
maintain that in a separate branch that could be merged in both DRM and
V4L2 without having to merge most of the other subsystem's pending
changes at the same time, but I think it's doable without any big issue.

> > If it's shared code, then it should be shared, and every client
> > framework put on an equal footing.
> >
> > > > - Develop the same library from within v4l2. That is really a poor
> > > > solution, since the information would be greatly duplicated
> > > > between the two, and in terms of maintainance, code, and binary
> > > > size that would be duplicated too.
> > >
> > > It's essentially what we decided to do for drm years back.
> >
> > And it was probably the right solution back then, but I'm really not
> > convinced it's still the right thing to do today.
> >
> > > > Having it shared allows to easily share, and discover formats from the
> > > > other subsystem, and to have a single, unique place where this is
> > > > centralized.
> > >
> > > What I think could work as middle ground:
> > > - Put drm_format stuff into a separate .ko
> > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > separate files. Not sure it's so convenient for v4l uapi.
> > > - Add a conversion library that tries to best-effort map between drm
> > > and v4l formats. On the drm side that most likely means you need
> > > offsets for planes, and modifiers too (since those are implied in some
> > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > the drivers that use this library need.
> > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > format space.
> > >
> > > Forcing this unification on everyone otoh is imo way too much.
> >
> > v4l2 is starting to converge with DRM, and we're using the DRM API
> > pretty much untouched for that library, so I'm not really sure how
> > anyone is hurt by that unification.
>
> It might make sense to regularly pull v4l updates into drm-next then
> anyway. That would also remove the need to have the format library
> somewhere else.

Are you saying it should the live in V4L2 ? ;-)

--
Regards,

Laurent Pinchart

2019-04-20 23:10:41

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Maxime,

On Thu, Apr 18, 2019 at 10:56:30PM +0200, Maxime Ripard wrote:
> On Thu, Apr 18, 2019 at 02:32:14PM +0200, Daniel Vetter wrote:
> >>>>> Unifying the formats themselves, and all the associated metadata is
> >>>>> imo a no-go, and was a pretty conscious decision when we implemented
> >>>>> drm_fourcc a few years back.
> >>>>>
> >>>>>> If we want to keep the current library in DRM, we have two options
> >>>>>> then:
> >>>>>>
> >>>>>> - Support all the v4l2 formats in the DRM library, which is
> >>>>>> essentially what I'm doing in the last patches. However, that
> >>>>>> would require to have the v4l2 developpers also reviewing stuff
> >>>>>> there. And given how busy they are, I cannot really see how that
> >>>>>> would work.
> >>>>>
> >>>>> Well, if we end up with a common library then yes we need cross
> >>>>> review. There's no way around that. Doesn't matter where exactly that
> >>>>> library is in the filesystem tree, and adding a special MAINTAINERS
> >>>>> entry for anything related to fourcc (both drm and v4l) to make sure
> >>>>> they get cross-posted is easy. No file renaming needed.
> >>>>
> >>>> That would create some governing issues as well. For example, if you
> >>>> ever have a patch from one fourcc addition (that might or might not be
> >>>> covered by v4l2), will you wait for any v4l2 developper to review it?
> >>>
> >>> None of this is fixed by code renaming or locations. Either way we
> >>> need to figure that out.
> >>>
> >>> And yes part of the reasons for not moving this out of drm is that I'm
> >>> not a fan of boutique trees for small stuff. If sharing means we need
> >>> to split the drm_fourcc code and library out of drm trees, I'm not
> >>> sure that's a good idea. We're already super liberal with merging
> >>> anything through driver trees with acks, and integrating them quickly
> >>> into drm-next. This would still be workable if v4l sends regular pull
> >>> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> >>> do). If we can only sync up once per merge window with a shared
> >>> boutique tree for formats only, life is going to be painful.
> >>
> >> I don't get why we want to turn DRM into some kind of a black hole
> >> that would pull everything. We don't have to, really. And at the same
> >> time it carries the message that v4l2 is less important than DRM for
> >> some reason, which I'm really not comfortable with.
> >
> > Make another tree somewhere that pulls in trees more often than every
> > merge window, and I'm happy. It's the coordination effort of lots of
> > trees that creates the black hole, not the other way round. Yes topic
> > trees work, but if topic trees are persistent something with the
> > organization of trees is wrong and needs to change. This very much
> > looks like we'll end up with a perpetual topic branch for format stuff
> > between drm and v4l.
>
> Well, if v4l2 sends a PR to DRM every 1 or 2 weeks, that definitely
> looks like a topic branch to me. And on a far more frequent basis than
> when we will merge a format description.
>
> > The other shared stuff (like hdmi infoframes) seems to change a lot
> > less often, so the occasional patch hasn't been a pain. But drm_fourcc
> > related stuff sees a lot of work, both in adding new formats and in
> > refactoring the library to keep up with all the new use-cases.
>
> When was the last time a refactoring that changed the API happened?
>
> Most of the changes will be new format descriptions, and I guess that
> would only concern a single tree.
>
> And really, we're doing this all the time, so I'm not sure what the
> big deal is here.
>
> I feel like there's something that you don't really like about this,
> but you're not saying this out loud.
>
> Sure, the exact process needs to be figured out, and everyone needs to
> agree upon that process. But that's pretty much it, and it's nothing
> out of the ordinary.
>
> > And yes I think an overall gfx-like-stuff.git tree for drm and v4l and
> > the few other bits really makes tons of sense. Not as a tree where
> > people commit, but as the 2nd-level integration tree (like drm.git
> > right now for gpu stuff).
> >
> >> And I don't really get why you're against this in the first
> >> place. When you have some code in a single driver that would benefit
> >> more driver, you create a helper and move it into the core.
> >
> > It's a feature that drm doesn't share that much code with other parts
> > of the kernel, it makes backporting the gfx stack to lts kernels a lot
> > easier. Until someone fixes the upstream kernel release model to no
> > longer need large scale gpu driver backports, we need to keep that.
> >
> >> In this case, we have some code used by a framework that more
> >> framework could use, and we move it to a core-er place. How is that
> >> different?
> >
> > Imo core sharing for code sharing's sake is overrated. If we already
> > have drm and v4l tightly integrated as a community, then code sharing
> > becomes a lot easier, and a lot more reasonable to do.
>
> At least Laurent, Boris, Ezequiel, Gustavo and I have been working on
> v4l2, so I'm not sure how not integrated we are.

Let's also mention that we'll need more code sharing as we move forward.
We already have chips that have two drivers, one in V4L2 and one in DRM
(I'm thinking about the adv7511 bridge driver for instance). I know SoC
vendors that are not happy about this state of things as they have IP
cores that can be used in both camera and display pipelines. It's a long
standing issue, it won't be solve today, but we'll need to get to it
eventually. Sharing a 4CC library would be a great step forward in my
opinion, in order to get the two subsystems to collaborate better.

> > Plus we can then just stuff code int drivers/gpu or drivers/video
> > (or merge these two because really it's all the same). But my
> > understanding is that integrating more tightly with the drm folks is
> > a very contreversial topic in v4l
>
> So, I sent the RFC expecting that kind of feedback.
>
> Hans replied mainly to that patch https://patchwork.freedesktop.org/patch/293043/
>
> "
> If we are creating a common library then I think we should change that rule
> to: "unless they are in use by a DRM or V4L2 driver". And when new formats are
> added, and they exists already for DRM or V4L2, then we should use the same
> fourcc for the other subsystem.
>
> I.e. if pixelformat V4L2_PIX_FMT_FOO was already defined, then add a:
>
> #define DRM_FORMAT_FOO V4L2_PIX_FMT_FOO
>
> rather than creating a new fourcc.

I would like to point out here that we have two different items we call
4CC, the macro name (FOO in your example here), and the numerical value.
If a numerical value already exists in DRM or V4L2 for a given pixel
format, it should be used, period. The macro name, however, could be
changed, as many of them carry historical mistakes.

> We could even start looking at redoing the whole scheme in a unified way, but
> that's something for the (far) future.
>
> This is already a big step forward.
> "
>
> So, not controversial at all.
>
> > and until that's resolved I don't see a huge need or benefit in
> > sharing tons of code.
>
> That's mostly tons of data though. The code is pretty small and
> trivial.
>
> > And the format stuff is a lot more central to kms than e.g. the
> > infoframe helpers.
> >
> > Au contraire, I think forcing this has a lot of potential for
> > needless fights between drm and v4l.
>
> We're all reasonable, so I'm not sure why we would need to fight here.
>
> > Hence my suggestion to try a minimal format conversion library
> > between the drm format world and the v4l format wolrd, and see how
> > that goes. That contains a lot less risk than going all in right
> > from the start.
>
> And it's really not about getting access to the DRM fourcc. It's about
> getting access to DRM's format description, so I'm not really sure
> what there is to convert, we just want a lookup.

--
Regards,

Laurent Pinchart

2019-04-23 07:27:24

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> Hi Daniel,
>
> On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> > On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> > > > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > > > Hi,
> > > > > > >
> > > > > > > DRM comes with an extensive format support to retrieve the various
> > > > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > > > development.
> > > > > > >
> > > > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > > > by that particular driver. This leads to a lot of duplication and
> > > > > > > boilerplate code in the v4l2 drivers.
> > > > > > >
> > > > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > > > used.
> > > > > > >
> > > > > > > Let me know what you think,
> > > > > > > Maxime
> > > > > > >
> > > > > > > Changes from RFC:
> > > > > > > - Rebased on next
> > > > > > > - Fixed the various formats mapping
> > > > > > > - Added tags
> > > > > > > - Did most of the formats functions as inline functions
> > > > > > > - Used a consistent prefix for all the utilities functions
> > > > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > > > arm64 and x86_64
> > > > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > > > functions
> > > > > > > - Added License and copyright headers on missing files
> > > > > > >
> > > > > > > Maxime Ripard (20):
> > > > > > > drm: Remove users of drm_format_num_planes
> > > > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > > > lib: Add video format information library
> > > > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > > > drm/malidp: Convert to generic image format library
> > > > > > > drm/client: Convert to generic image format library
> > > > > > > drm/exynos: Convert to generic image format library
> > > > > > > drm/i915: Convert to generic image format library
> > > > > > > drm/ipuv3: Convert to generic image format library
> > > > > > > drm/msm: Convert to generic image format library
> > > > > > > drm/omap: Convert to generic image format library
> > > > > > > drm/rockchip: Convert to generic image format library
> > > > > > > drm/tegra: Convert to generic image format library
> > > > > > > drm/fourcc: Remove old DRM format API
> > > > > > > lib: image-formats: Add v4l2 formats support
> > > > > > > lib: image-formats: Add more functions
> > > > > > > media: sun6i: Convert to the image format API
> > > > > >
> > > > > > In the interest of making myself unpopular: Why move this out of drm?
> > > > > >
> > > > > > We do have a bunch of other such shared helpers already (mostly in
> > > > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > > > sure that's going better than keeping it maintained in drm.
>
> That's a bit of a different situation as both DRM and FBDEV address the
> same features (display output), and FBDEV is deprecared and replaced by
> DRM.
>
> I'm not against maintaining a 4CC library in DRM (adding a third-party
> maintainer would likely create more problems than it would solve), but
> that doesn't mean the library has to live in drivers/gpu/, nor that it
> needs to have the drm_ prefix. I would actually advocate to make it live
> in a neutral directory, with a neutral prefix (kudos to anyone who can
> propose a nice naming convention that would establish a new shared
> ground for image/video-related Linux APIs), and maintained through the
> DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> reaches all the related folks).
>
> > > > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > > > dropping the drm prefix isn't going to help I think.
> > > > > >
> > > > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > > > use it without dragging in all of drm), and we need to add some fields for
> > > > > > converting to v4l fourcc codes (which are different). But that should be
> > > > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > > > it's actually a feature: It makes it really clear that these are the drm
> > > > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > > > that. That allocation authority is also already baked into various khr/ext
> > > > > > standards, too.
>
> There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> documentation. Look at
> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> or
> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> for instance. It's painful to write, painful to read, but defines the
> 4CCs very clearly without ambiguity. I wouldn't be surprised if
> different drivers used the same DRM 4CC for different formats due to the
> lack of detailed documentation. Moving to a shared library for 4CCs
> should also address the documentation side, and any new format added to
> the kernel, whether from the V4L2 side or the DRM side, would be
> required to provide detailed documentation. That would be a great
> improvement for DRM 4CC handling.
>
> > > > > The way I see it, there's a fundamental difference between the UAPI
> > > > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > > > authority, it's all fine.
> > > > >
> > > > > Internally however, the long term goal is to share the fourcc's
> > > > > between DRM and V4L2 for the same formats. It basically means that of
> > > > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > > > already extensive v4l2 formats support.
> > > >
> > > > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > > > format identifier space.
> > >
> > > No to what exactly?
> > >
> > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > really it's totally not.
> > >
> > > Even if it's not a standard, having consistency would be a good thing.
> > >
> > > And you said yourself that DRM fourcc is now pretty much an authority
> > > for the fourcc, so it definitely looks like a standard to me.
> >
> > drm fourcc is the authority for drm fourcc codes. Not for any of the
> > others (and there's lots of them). Now it's used in a bunch of other
> > places (khr standards, dri protocols in wayland/X11), but they're
> > still only drm fourcc. There is no overall fourcc standard.
> >
> > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > in modifiers a lot more.
> > >
> > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > converging here, and we can totally have a layer in v4l2 to convert
> > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > >
> > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > valid as ever:
> > > >
> > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > can't use them and need a duplicated DRM_FOURCC code.
> > >
> > > Do yo have an example of one of those areas?
> >
> > I think the rgb stuff was one of the big reasons to not reuse any
> > existing fourcc standard (whether v4l, or another one from e.g. video
> > container formats). We had initial patches to reuse the fourcc that
> > existed, but the end result was really inconsistent, so we ditch that
> > and rolled out a new set of entirely drm specific fourcc codes for
> > rgba.
>
> Could you give one or a couple of examples of V4L2 4CCs that are not
> OCD-compatible ? :-)
>
> > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > e.g. offset for planar yuv formats, or tiling mode
> > >
> > > As I was saying, this changes on the v4l2 side, and converging to
> > > what DRM is doing.
> > >
> > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > uniquely, drivers can override that (that's an explicit design
> > > > intent of modifiers, to allow drivers to add another plane for
> > > > e.g. compression information). You'd need to pull that driver
> > > > knowledge into your format library.
>
> That's a mistake in my opinion. We tried that in V4L2 to store metadata
> in a separate plane, and had to go another route eventually as it
> created a very bad mess.

Just quick clarification in the middle here: This is how the hw works.
It's not metadata that sw ever touches (in general, testcases to make sure
we display these correctly excepted).

There has been some talking to add maybe a bit more mixed metadata, for
fast-clear colors (which isn't used by any display engine afaik yet). That
would generally be written by the cpu (in the gl stack), but again read by
the hw (loaded as indirect state packet most likely, or something like
that). So again hw specific layout, because the hw needs to read it.

Pure metadata only of interest for the cpu/sw stack has been shot down
completely on the drm side too.

> There's a tendency in both subsystems to look at the other as a bit of a
> retarded relative, and that's a shame, we have lots to learn from each
> other's mistakes. That wouldn't be too difficult if people started
> talking to each other.
>
> A semi-related comment: DRM also carries other mistakes of its own, I'm
> thinking about DRM_FORMAT_BIG_ENDIAN in particular

Yeah that one is hilarios, but in practice big endian is dead, except for
a very few server chips, and there I think Gerd's work mostly fixed up
that mess.

> > > I'm not sure how my patches are changing anything here. This is
> > > litterally the same code, with the functions renamed.
> > >
> > > If drivers want to override that, then yeah, fine, we can let them do
> > > that. Just like any helper this just provides a default that covers
> > > most of the cases.
> > >
> > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > something like a new addfb flag.
> > >
> > > For the formats that would be described as a modifier, sure. For all
> > > the others (that are not yet supported by DRM), then I don't really
> > > see why not.
> >
> > See above, we tried that initially, didn't pass the ocd tests when
> > reviewing. Maybe the situation is better outside of rbgx/a formats,
> > and I think we do at least try to use the same fourcc codes there when
> > there already is one. But then the details occasionally look
> > different.
> >
> > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > >
> > > > > Having a shared library, governed by both, will make this far easier,
> > > > > since it will be easy to discover the formats that are already
> > > > > supported by the other subsystem.
> > > >
> > > > I think a compat library that (tries to, best effort) convert between
> > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > to the conversion functions for videomode <-> drm_display_mode
> > > > perhaps. That should be useful for drivers.
> > >
> > > That's not really what this series is about though. That series is
> > > about sharing the (image|pixels) formats database across everyone so
> > > that everyone can benefit from it.
> >
> > Yeah I know. I still think leaving the drm fourcc with the drm prefix
> > would be good, since there's really no standard here.
> >
> > > > Unifying the formats themselves, and all the associated metadata is
> > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > drm_fourcc a few years back.
> > > >
> > > > > If we want to keep the current library in DRM, we have two options
> > > > > then:
> > > > >
> > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > essentially what I'm doing in the last patches. However, that
> > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > there. And given how busy they are, I cannot really see how that
> > > > > would work.
> > > >
> > > > Well, if we end up with a common library then yes we need cross
> > > > review. There's no way around that. Doesn't matter where exactly that
> > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > they get cross-posted is easy. No file renaming needed.
> > >
> > > That would create some governing issues as well. For example, if you
> > > ever have a patch from one fourcc addition (that might or might not be
> > > covered by v4l2), will you wait for any v4l2 developper to review it?
> >
> > None of this is fixed by code renaming or locations. Either way we
> > need to figure that out.
> >
> > And yes part of the reasons for not moving this out of drm is that I'm
> > not a fan of boutique trees for small stuff. If sharing means we need
> > to split the drm_fourcc code and library out of drm trees, I'm not
> > sure that's a good idea. We're already super liberal with merging
> > anything through driver trees with acks, and integrating them quickly
> > into drm-next. This would still be workable if v4l sends regular pull
> > requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > do). If we can only sync up once per merge window with a shared
> > boutique tree for formats only, life is going to be painful.
>
> That should be solved by the proposal above, maintaining the shared
> library in the DRM tree. We would need to be careful there, and ideally
> maintain that in a separate branch that could be merged in both DRM and
> V4L2 without having to merge most of the other subsystem's pending
> changes at the same time, but I think it's doable without any big issue.
>
> > > If it's shared code, then it should be shared, and every client
> > > framework put on an equal footing.
> > >
> > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > solution, since the information would be greatly duplicated
> > > > > between the two, and in terms of maintainance, code, and binary
> > > > > size that would be duplicated too.
> > > >
> > > > It's essentially what we decided to do for drm years back.
> > >
> > > And it was probably the right solution back then, but I'm really not
> > > convinced it's still the right thing to do today.
> > >
> > > > > Having it shared allows to easily share, and discover formats from the
> > > > > other subsystem, and to have a single, unique place where this is
> > > > > centralized.
> > > >
> > > > What I think could work as middle ground:
> > > > - Put drm_format stuff into a separate .ko
> > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > - Add a conversion library that tries to best-effort map between drm
> > > > and v4l formats. On the drm side that most likely means you need
> > > > offsets for planes, and modifiers too (since those are implied in some
> > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > the drivers that use this library need.
> > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > format space.
> > > >
> > > > Forcing this unification on everyone otoh is imo way too much.
> > >
> > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > pretty much untouched for that library, so I'm not really sure how
> > > anyone is hurt by that unification.
> >
> > It might make sense to regularly pull v4l updates into drm-next then
> > anyway. That would also remove the need to have the format library
> > somewhere else.
>
> Are you saying it should the live in V4L2 ? ;-)

Maybe a few clarifications on how the drm shared core thing usually works,
and why I'm a sticker here. Bottom reply since I'm not sure where to put
it:

- Refactorings usually go in through drm-misc (at least since a few
years).

- Small patches go in through the relevant driver tree (which is often
drm-misc, but not always), with an Ack from drm maintainers.

- No topic branches, everyone just pushes patches where it's most
convenient.

We get away with this mess because everyone sends regular pull requests to
drm, where the entire history is baked in and others can backmerge/fast
forward/rebase. Worst case you wait one month (around the merge window,
when drm-next is closed for features), but usually it's just 1-2 weeks.
Plus we tend to have fairly big trees, with good chances that the next
patch series lands in the same tree again and no work at all is needed.

If we start regularly sharing lots of code with v4l (which seems to be the
long term goal here), then I think we need something equally convenient
for all that.

We're not going to be able to teach some complicated topic branch scheme
to the 50+ submaintainers/committers we have in drm - a lot much more
basic stuff already takes lots of work to get it to stick. If the proposal
is "to be careful" and "maintain it in a separate branch", I'm not in
favour because I think that just wouldn't work.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

2019-04-23 07:31:43

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> Hi Paul,
>
> On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > >> And a lot of people pushed for the "fourcc is a standard", when
> > >> really it's totally not.
> > >
> > > Even if it's not a standard, having consistency would be a good thing.
> > >
> > > And you said yourself that DRM fourcc is now pretty much an authority
> > > for the fourcc, so it definitely looks like a standard to me.
> >
> > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > cause, as it has already significantly diverged. Even if we coordinate
> > an effort to introduce new formats with the same fourcc on both sides,
> > I don't see what good that would be since the formats we have now are
> > still plagued by the inconsistency.
> >
> > I think we always need an explicit translation step from either v4l2 or
> > drm to the internal representation and back, without ever assuming that
> > formats might be compatible because they share the same fourcc.
>
> I don't agree. APIs evolve, and while we can't switch from one set of
> 4CCs to another in existing APIs, we could in new APIs. Boris is working
> on new ioctls to handle formats in V4L2, and while 4CC unification could
> be impopular from a userspace developers point of view there, I don't
> think we have ruled it out completely. The move to the request API is
> also an area where a common set of 4CCs could be used, as it will depart
> from the existing V4L2 ioctls. To summarize my opinion, we're not there
> yet, but I wouldn't rule it out completely for the future.
>
> > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > modifier.
>
> DRM modifiers are mostly about tiling and compression, and we hardly
> support these in V4L2. What are the modifiers you think are hardcoded in
> 4CCs in V4L2 ?

Hm maybe it was a drm one that didn't come from v4l or anywhere else
really, but the NV12MT one is nv12 + some tiling. I think we managed to
uapi-bend that one into shape in at least drm.
-Daniel

> > I think Boris (CCed) is working to change that by allowing to
> > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > where some formats are described by the v4l2 pixfmt alone and some
> > formats are also described a modifier (but I looked at it from a
> > distance so might have misunderstod). That feels better since it avoids
> > the combinatory explosion from describing each format + modifier
> > individually.
> >
> > What do you think?
> >
> > >> v4l tends to conflate pixel format with stuff that we tend to encode
> > >> in modifiers a lot more.
> > >
> > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > converging here, and we can totally have a layer in v4l2 to convert
> > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > >
> > >> There's a bunch of reasons we can't just use v4l, and they're as
> > >> valid as ever:
> > >>
> > >> - We overlap badly in some areas, so even if fourcc codes match, we
> > >> can't use them and need a duplicated DRM_FOURCC code.
> > >
> > > Do yo have an example of one of those areas?
> > >
> > >> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > >> e.g. offset for planar yuv formats, or tiling mode
> > >
> > > As I was saying, this changes on the v4l2 side, and converging to
> > > what DRM is doing.
> > >
> > >> - drm fourcc code doesn't actually define the drm_format_info
> > >> uniquely, drivers can override that (that's an explicit design
> > >> intent of modifiers, to allow drivers to add another plane for
> > >> e.g. compression information). You'd need to pull that driver
> > >> knowledge into your format library.
> > >
> > > I'm not sure how my patches are changing anything here. This is
> > > litterally the same code, with the functions renamed.
> > >
> > > If drivers want to override that, then yeah, fine, we can let them do
> > > that. Just like any helper this just provides a default that covers
> > > most of the cases.
> > >
> > >> Iow there's no way we can easily adopt v4l fourcc, except if we do
> > >> something like a new addfb flag.
> > >
> > > For the formats that would be described as a modifier, sure. For all
> > > the others (that are not yet supported by DRM), then I don't really
> > > see why not.
> > >
> > >>> And given how the current state is a mess in this regard, I'm not too
> > >>> optimistic about keeping the formats in their relevant frameworks.
> > >>>
> > >>> Having a shared library, governed by both, will make this far easier,
> > >>> since it will be easy to discover the formats that are already
> > >>> supported by the other subsystem.
> > >>
> > >> I think a compat library that (tries to, best effort) convert between
> > >> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > >> to the conversion functions for videomode <-> drm_display_mode
> > >> perhaps. That should be useful for drivers.
> > >
> > > That's not really what this series is about though. That series is
> > > about sharing the (image|pixels) formats database across everyone so
> > > that everyone can benefit from it.
> > >
> > >> Unifying the formats themselves, and all the associated metadata is
> > >> imo a no-go, and was a pretty conscious decision when we implemented
> > >> drm_fourcc a few years back.
> > >>
> > >>> If we want to keep the current library in DRM, we have two options
> > >>> then:
> > >>>
> > >>> - Support all the v4l2 formats in the DRM library, which is
> > >>> essentially what I'm doing in the last patches. However, that
> > >>> would require to have the v4l2 developpers also reviewing stuff
> > >>> there. And given how busy they are, I cannot really see how that
> > >>> would work.
> > >>
> > >> Well, if we end up with a common library then yes we need cross
> > >> review. There's no way around that. Doesn't matter where exactly that
> > >> library is in the filesystem tree, and adding a special MAINTAINERS
> > >> entry for anything related to fourcc (both drm and v4l) to make sure
> > >> they get cross-posted is easy. No file renaming needed.
> > >
> > > That would create some governing issues as well. For example, if you
> > > ever have a patch from one fourcc addition (that might or might not be
> > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > >
> > > If it's shared code, then it should be shared, and every client
> > > framework put on an equal footing.
> > >
> > >>> - Develop the same library from within v4l2. That is really a poor
> > >>> solution, since the information would be greatly duplicated
> > >>> between the two, and in terms of maintainance, code, and binary
> > >>> size that would be duplicated too.
> > >>
> > >> It's essentially what we decided to do for drm years back.
> > >
> > > And it was probably the right solution back then, but I'm really not
> > > convinced it's still the right thing to do today.
> > >
> > >>> Having it shared allows to easily share, and discover formats from the
> > >>> other subsystem, and to have a single, unique place where this is
> > >>> centralized.
> > >>
> > >> What I think could work as middle ground:
> > >> - Put drm_format stuff into a separate .ko
> > >> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > >> posted to both drm and v4l lists. Easy on the drm side, since it's all
> > >> separate files. Not sure it's so convenient for v4l uapi.
> > >> - Add a conversion library that tries to best-effort map between drm
> > >> and v4l formats. On the drm side that most likely means you need
> > >> offsets for planes, and modifiers too (since those are implied in some
> > >> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > >> the drivers that use this library need.
> > >> - Add drm_fourcc as-needed by these drivers that want to use a unified
> > >> format space.
> > >>
> > >> Forcing this unification on everyone otoh is imo way too much.
> > >
> > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > pretty much untouched for that library, so I'm not really sure how
> > > anyone is hurt by that unification.
>
> --
> Regards,
>
> Laurent Pinchart

--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

2019-04-23 09:01:17

by Daniel Stone

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Tue, 23 Apr 2019 at 08:26, Daniel Vetter <[email protected]> wrote:
> On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > uniquely, drivers can override that (that's an explicit design
> > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > e.g. compression information). You'd need to pull that driver
> > > > > knowledge into your format library.
> >
> > That's a mistake in my opinion. We tried that in V4L2 to store metadata
> > in a separate plane, and had to go another route eventually as it
> > created a very bad mess.
>
> Just quick clarification in the middle here: This is how the hw works.
> It's not metadata that sw ever touches (in general, testcases to make sure
> we display these correctly excepted).
>
> There has been some talking to add maybe a bit more mixed metadata, for
> fast-clear colors (which isn't used by any display engine afaik yet). That
> would generally be written by the cpu (in the gl stack), but again read by
> the hw (loaded as indirect state packet most likely, or something like
> that). So again hw specific layout, because the hw needs to read it.
>
> Pure metadata only of interest for the cpu/sw stack has been shot down
> completely on the drm side too.

Totally. Let's take DRM_FORMAT_XRGB8888 + I915_FORMAT_MOD_Y_TILED as
an example. Here, there is one colour plane which is laid out in a
documented tiled format, containing normal XRGB8888 pixels once you do
the maths to get the correct pixel location. So that's fine.

I915_FORMAT_MOD_Y_TILED_CCS has a base colour plane as above, but adds
an auxiliary plane which has a few bits describing the state of every
(differently-sized) tile. Before reading the tile from the colour
plane, you look at the corresponding location in the auxiliary plane:
if you read 0x55 from the auxiliary plane, then the entire cacheline
is the value of the first pixel, i.e. a solid fill. Hardware takes
advantage of this to only write out the first pixel: if you try to
read the colour plane as Y_TILED then for solid-filled regions, only
the first pixel of every tile will show correctly, and the rest will
be garbage.

The auxiliary plane has its own layout and placement requirements, so
we need to carry around an offset and a stride for the auxiliary data.
We already have this for multiple planes; stuffing it into the base
plane would require us to reinvent the same for auxiliary data within
a single plane.

I understand at least one of the Tegra colour-compression layouts (for
Tegra 1xx?) is similar to this.

It would be good to understand what you had in mind when you said that
using multiple planes created a mess. I haven't touched media
encode/decode units at a low level for quite a while (hooray for
gst-v4l2!), but I remember that they often used padding areas around
the buffer for scratch space - maybe motion vectors or similar? That
case is quite different to something like CCS, since the data is only
meaningful to the media engine and must be ignored (but preserved) by
everyone else. Using multiple planes in that case isn't appropriate,
since it's very specific to how that hardware unit deals with that
buffer, instead of something that every consumer needs to understand
in order to use it.

Cheers,
Daniel

2019-04-23 11:24:39

by Thomas Zimmermann

[permalink] [raw]
Subject: Re: [PATCH 06/20] lib: Add video format information library

Hi

Am 17.04.19 um 09:54 schrieb Maxime Ripard:
> Move the DRM formats API to turn this into a more generic image formats API
> to be able to leverage it into some other places of the kernel, such as
> v4l2 drivers.

Here's some nitpicking: 'image_format_*' appears slightly vague; it
could refer to a disk or ROM image as well. Something like
'pixel_format_*', 'pixbuf_format_*', etc. would clearly indicate graphics.

Best regards
Thomas

>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> include/linux/image-formats.h | 387 +++++++++++++++++++++-
> lib/Kconfig | 7 +-
> lib/Makefile | 3 +-
> lib/image-formats-selftests.c | 325 +++++++++++++++++-
> lib/image-formats.c | 655 +++++++++++++++++++++++++++++++++++-
> 5 files changed, 1377 insertions(+)
> create mode 100644 include/linux/image-formats.h
> create mode 100644 lib/image-formats-selftests.c
> create mode 100644 lib/image-formats.c
>
> diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> new file mode 100644
> index 000000000000..ec43d9f9a527
> --- /dev/null
> +++ b/include/linux/image-formats.h
> @@ -0,0 +1,387 @@
> +/*
> + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> + *
> + * 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.
> + */
> +
> +#ifndef _IMAGE_FORMATS_H_
> +#define _IMAGE_FORMATS_H_
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +
> +/**
> + * struct image_format_info - information about a image format
> + */
> +struct image_format_info {
> + union {
> + /**
> + * @drm_fmt:
> + *
> + * DRM 4CC format identifier (DRM_FORMAT_*)
> + */
> + u32 drm_fmt;
> +
> + /**
> + * @format:
> + *
> + * DRM 4CC format identifier (DRM_FORMAT_*). Kept
> + * around for compatibility reasons with the current
> + * DRM drivers.
> + */
> + u32 format;
> + };
> +
> + /**
> + * @depth:
> + *
> + * Color depth (number of bits per pixel excluding padding bits),
> + * valid for a subset of RGB formats only. This is a legacy field, do
> + * not use in new code and set to 0 for new formats.
> + */
> + u8 depth;
> +
> + /** @num_planes: Number of color planes (1 to 3) */
> + u8 num_planes;
> +
> + union {
> + /**
> + * @cpp:
> + *
> + * Number of bytes per pixel (per plane), this is aliased with
> + * @char_per_block. It is deprecated in favour of using the
> + * triplet @char_per_block, @block_w, @block_h for better
> + * describing the pixel format.
> + */
> + u8 cpp[3];
> +
> + /**
> + * @char_per_block:
> + *
> + * Number of bytes per block (per plane), where blocks are
> + * defined as a rectangle of pixels which are stored next to
> + * each other in a byte aligned memory region. Together with
> + * @block_w and @block_h this is used to properly describe tiles
> + * in tiled formats or to describe groups of pixels in packed
> + * formats for which the memory needed for a single pixel is not
> + * byte aligned.
> + *
> + * @cpp has been kept for historical reasons because there are
> + * a lot of places in drivers where it's used. In drm core for
> + * generic code paths the preferred way is to use
> + * @char_per_block, image_format_info_block_width() and
> + * image_format_info_block_height() which allows handling both
> + * block and non-block formats in the same way.
> + *
> + * For formats that are intended to be used only with non-linear
> + * modifiers both @cpp and @char_per_block must be 0 in the
> + * generic format table. Drivers could supply accurate
> + * information from their drm_mode_config.get_format_info hook
> + * if they want the core to be validating the pitch.
> + */
> + u8 char_per_block[3];
> + };
> +
> + /**
> + * @block_w:
> + *
> + * Block width in pixels, this is intended to be accessed through
> + * image_format_info_block_width()
> + */
> + u8 block_w[3];
> +
> + /**
> + * @block_h:
> + *
> + * Block height in pixels, this is intended to be accessed through
> + * image_format_info_block_height()
> + */
> + u8 block_h[3];
> +
> + /** @hsub: Horizontal chroma subsampling factor */
> + u8 hsub;
> + /** @vsub: Vertical chroma subsampling factor */
> + u8 vsub;
> +
> + /** @has_alpha: Does the format embeds an alpha component? */
> + bool has_alpha;
> +
> + /** @is_yuv: Is it a YUV format? */
> + bool is_yuv;
> +};
> +
> +/**
> + * image_format_info_is_yuv_packed - check that the format info matches a YUV
> + * format with data laid in a single plane
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a packed YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_packed(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_semiplanar - check that the format info matches a YUV
> + * format with data laid in two planes (luminance and chrominance)
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a semiplanar YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_semiplanar(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 2;
> +}
> +
> +/**
> + * image_format_info_is_yuv_planar - check that the format info matches a YUV
> + * format with data laid in three planes (one for each YUV component)
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a planar YUV format.
> + */
> +static inline bool
> +image_format_info_is_yuv_planar(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->num_planes == 3;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_410 - check that the format info matches a
> + * YUV format with 4:1:0 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:1:0
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_410(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 4 && info->vsub == 4;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_411 - check that the format info matches a
> + * YUV format with 4:1:1 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:1:1
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_411(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 4 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_420 - check that the format info matches a
> + * YUV format with 4:2:0 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:2:0
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_420(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 2 && info->vsub == 2;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_422 - check that the format info matches a
> + * YUV format with 4:2:2 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:2:2
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_422(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 2 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_is_yuv_sampling_444 - check that the format info matches a
> + * YUV format with 4:4:4 sub-sampling
> + * @info: format info
> + *
> + * Returns:
> + * A boolean indicating whether the format info matches a YUV format with 4:4:4
> + * sub-sampling.
> + */
> +static inline bool
> +image_format_info_is_yuv_sampling_444(const struct image_format_info *info)
> +{
> + return info->is_yuv && info->hsub == 1 && info->vsub == 1;
> +}
> +
> +/**
> + * image_format_info_plane_cpp - determine the bytes per pixel value
> + * @format: pixel format info
> + * @plane: plane index
> + *
> + * Returns:
> + * The bytes per pixel value for the specified plane.
> + */
> +static inline
> +int image_format_info_plane_cpp(const struct image_format_info *info, int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + return info->cpp[plane];
> +}
> +
> +/**
> + * image_format_info_plane_width - width of the plane given the first plane
> + * @format: pixel format info
> + * @width: width of the first plane
> + * @plane: plane index
> + *
> + * Returns:
> + * The width of @plane, given that the width of the first plane is @width.
> + */
> +static inline
> +int image_format_info_plane_width(const struct image_format_info *info, int width,
> + int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + if (plane == 0)
> + return width;
> +
> + return width / info->hsub;
> +}
> +
> +/**
> + * image_format_info_plane_height - height of the plane given the first plane
> + * @format: pixel format info
> + * @height: height of the first plane
> + * @plane: plane index
> + *
> + * Returns:
> + * The height of @plane, given that the height of the first plane is @height.
> + */
> +static inline
> +int image_format_info_plane_height(const struct image_format_info *info, int height,
> + int plane)
> +{
> + if (!info || plane >= info->num_planes)
> + return 0;
> +
> + if (plane == 0)
> + return height;
> +
> + return height / info->vsub;
> +}
> +
> +/**
> + * image_format_info_block_width - width in pixels of block.
> + * @format: pointer to the image_format_info
> + * @plane: plane index
> + *
> + * Returns:
> + * The width in pixels of a block, depending on the plane index.
> + */
> +static inline
> +unsigned int image_format_info_block_width(const struct image_format_info *format,
> + int plane)
> +{
> + if (!format)
> + return 0;
> +
> + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> + return 0;
> +
> + if (plane >= format->num_planes)
> + return 0;
> +
> + if (!format->block_w[plane])
> + return 1;
> +
> + return format->block_w[plane];
> +}
> +
> +/**
> + * image_format_info_block_height - height in pixels of a block
> + * @info: pointer to the image_format_info
> + * @plane: plane index
> + *
> + * Returns:
> + * The height in pixels of a block, depending on the plane index.
> + */
> +static inline
> +unsigned int image_format_info_block_height(const struct image_format_info *format,
> + int plane)
> +{
> + if (!format)
> + return 0;
> +
> + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> + return 0;
> +
> + if (plane >= format->num_planes)
> + return 0;
> +
> + if (!format->block_h[plane])
> + return 1;
> +
> + return format->block_h[plane];
> +}
> +
> +/**
> + * image_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.
> + */
> +static inline
> +uint64_t image_format_info_min_pitch(const struct image_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],
> + image_format_info_block_width(info, plane) *
> + image_format_info_block_height(info, plane));
> +}
> +
> +const struct image_format_info *__image_format_drm_lookup(u32 drm);
> +const struct image_format_info *image_format_drm_lookup(u32 drm);
> +
> +#endif /* _IMAGE_FORMATS_H_ */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index fb453afff32e..9a0160d3123b 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -625,3 +625,10 @@ config GENERIC_LIB_UCMPDI2
>
> config OBJAGG
> tristate "objagg" if COMPILE_TEST
> +
> +config IMAGE_FORMATS
> + bool
> +
> +config IMAGE_FORMATS_SELFTESTS
> + tristate "Test image format functions"
> + depends on IMAGE_FORMATS
> diff --git a/lib/Makefile b/lib/Makefile
> index 6996d2b9f401..203336b91248 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -280,3 +280,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
> obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
> obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
> obj-$(CONFIG_OBJAGG) += objagg.o
> +
> +obj-$(CONFIG_IMAGE_FORMATS) += image-formats.o
> +obj-$(CONFIG_IMAGE_FORMATS_SELFTESTS) += image-formats-selftests.o
> diff --git a/lib/image-formats-selftests.c b/lib/image-formats-selftests.c
> new file mode 100644
> index 000000000000..d0f0011b535e
> --- /dev/null
> +++ b/lib/image-formats-selftests.c
> @@ -0,0 +1,325 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Test cases for the image_format functions
> + */
> +
> +#define pr_fmt(fmt) "image_format: " fmt
> +
> +#include <linux/errno.h>
> +#include <linux/image-formats.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <drm/drm_fourcc.h>
> +
> +#define FAIL(test, msg, ...) \
> + do { \
> + if (test) { \
> + pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
> + return -EINVAL; \
> + } \
> + } while (0)
> +
> +#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
> +
> +static int test_image_format_info_block_width(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_block_width(info, 0) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> +
> + /* Test 1 plane format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> + FAIL_ON(image_format_info_block_width(info, 2) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test 3 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> + FAIL_ON(image_format_info_block_width(info, 2) != 1);
> + FAIL_ON(image_format_info_block_width(info, 3) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + /* Test a tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_width(info, 0) != 2);
> + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> +
> + return 0;
> +}
> +
> +static int test_image_format_info_block_height(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_block_height(info, 0) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> +
> + /* Test 1 plane format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> + FAIL_ON(image_format_info_block_height(info, 2) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test 3 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> + FAIL_ON(image_format_info_block_height(info, 2) != 1);
> + FAIL_ON(image_format_info_block_height(info, 3) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + /* Test a tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_block_height(info, 0) != 2);
> + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> +
> + return 0;
> +}
> +
> +static int test_image_format_info_min_pitch(void)
> +{
> + const struct image_format_info *info = NULL;
> +
> + /* Test invalid arguments */
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + /* Test 1 plane 8 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_RGB332);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1));
> +
> + /* Test 1 plane 16 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1) * 2);
> +
> + /* Test 1 plane 24 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_RGB888);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 3);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 6);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 3072);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 5760);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 12288);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2013);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 3);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 3);
> +
> + /* Test 1 plane 32 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_ABGR8888);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 8);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 2560);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 7680);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 16384);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2684);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 4);
> +
> + /* Test 2 planes format */
> + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 672);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> + (uint64_t)(UINT_MAX - 1));
> + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1));
> +
> + /* Test 3 planes 8 bits per pixel format */
> + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 3, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 1) != 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 2) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 320);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 320) != 320);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 512);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 512) != 512);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 960);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 960) != 960);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 2048) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 336);
> + FAIL_ON(image_format_info_min_pitch(info, 2, 336) != 336);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX);
> + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX / 2 + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
> + (uint64_t)UINT_MAX / 2 + 1);
> + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> + FAIL_ON(image_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
> + (uint64_t)(UINT_MAX - 1) / 2);
> +
> + /* Test tiled format */
> + info = image_format_drm_lookup(DRM_FORMAT_X0L2);
> + FAIL_ON(!info);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> +
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> + (uint64_t)UINT_MAX * 2);
> + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> + (uint64_t)(UINT_MAX - 1) * 2);
> +
> + return 0;
> +}
> +
> +#define selftest(test) { .name = #test, .func = test, }
> +
> +static struct image_format_test {
> + char *name;
> + int (*func)(void);
> +} tests[] = {
> + selftest(test_image_format_info_block_height),
> + selftest(test_image_format_info_block_width),
> + selftest(test_image_format_info_min_pitch),
> +};
> +
> +static int __init image_format_test_init(void)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(tests); i++) {
> + struct image_format_test *test = &tests[i];
> + int ret;
> +
> + ret = test->func();
> + if (ret) {
> + pr_err("Failed test %s\n", test->name);
> + return ret;
> + }
> + }
> +
> + pr_info("All tests executed properly.\n");
> + return 0;
> +}
> +module_init(image_format_test_init);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_AUTHOR("Maxime Ripard <[email protected]>");
> +MODULE_LICENSE("GPL");
> diff --git a/lib/image-formats.c b/lib/image-formats.c
> new file mode 100644
> index 000000000000..1e52a7410222
> --- /dev/null
> +++ b/lib/image-formats.c
> @@ -0,0 +1,655 @@
> +/*
> + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> + *
> + * 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/image-formats.h>
> +#include <linux/kernel.h>
> +#include <linux/math64.h>
> +
> +#include <uapi/drm/drm_fourcc.h>
> +
> +static const struct image_format_info formats[] = {
> + {
> + .drm_fmt = DRM_FORMAT_C8,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB332,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR233,
> + .depth = 8,
> + .num_planes = 1,
> + .cpp = { 1, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA4444,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR1555,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA5551,
> + .depth = 15,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB565,
> + .depth = 16,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR565,
> + .depth = 16,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 3, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 3, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX8888,
> + .depth = 24,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB565_A8,
> + .depth = 24,
> + .num_planes = 2,
> + .cpp = { 2, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR565_A8,
> + .depth = 24,
> + .num_planes = 2,
> + .cpp = { 2, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR2101010,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA1010102,
> + .depth = 30,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ARGB8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_ABGR8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBA8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRA8888,
> + .depth = 32,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGB888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 3, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGR888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 3, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XRGB8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XBGR8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_RGBX8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_BGRX8888_A8,
> + .depth = 32,
> + .num_planes = 2,
> + .cpp = { 4, 1, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV410,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 4,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU410,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 4,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV411,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU411,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 4,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV420,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU420,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV422,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU422,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUV444,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVU444,
> + .depth = 0,
> + .num_planes = 3,
> + .cpp = { 1, 1, 1 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV12,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV21,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 2,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV16,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV61,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV24,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_NV42,
> + .depth = 0,
> + .num_planes = 2,
> + .cpp = { 1, 2, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YUYV,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_YVYU,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_UYVY,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_VYUY,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 2, 0, 0 },
> + .hsub = 2,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_XYUV8888,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = DRM_FORMAT_AYUV,
> + .depth = 0,
> + .num_planes = 1,
> + .cpp = { 4, 0, 0 },
> + .hsub = 1,
> + .vsub = 1,
> + .has_alpha = true,
> + .is_yuv = true,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + }, {
> + .drm_fmt = 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,
> + },
> +};
> +
> +#define __image_format_lookup(_field, _fmt) \
> + ({ \
> + const struct image_format_info *format = NULL; \
> + unsigned i; \
> + \
> + for (i = 0; i < ARRAY_SIZE(formats); i++) \
> + if (formats[i]._field == _fmt) \
> + format = &formats[i]; \
> + \
> + format; \
> + })
> +
> +/**
> + * __image_format_drm_lookup - query information for a given format
> + * @drm: DRM fourcc pixel format (DRM_FORMAT_*)
> + *
> + * The caller should only pass a supported pixel format to this function.
> + *
> + * Returns:
> + * The instance of struct image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *__image_format_drm_lookup(u32 drm)
> +{
> + return __image_format_lookup(drm_fmt, drm);
> +}
> +EXPORT_SYMBOL(__image_format_drm_lookup);
> +
> +/**
> + * image_format_drm_lookup - query information for a given format
> + * @drm: DRM fourcc 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 image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *image_format_drm_lookup(u32 drm)
> +{
> + const struct image_format_info *format;
> +
> + format = __image_format_drm_lookup(drm);
> +
> + WARN_ON(!format);
> + return format;
> +}
> +EXPORT_SYMBOL(image_format_drm_lookup);
>

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)


Attachments:
signature.asc (499.00 B)
OpenPGP digital signature

2019-04-23 12:36:03

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > Hi Paul,
> >
> > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > really it's totally not.
> > > >
> > > > Even if it's not a standard, having consistency would be a good thing.
> > > >
> > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > for the fourcc, so it definitely looks like a standard to me.
> > >
> > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > cause, as it has already significantly diverged. Even if we coordinate
> > > an effort to introduce new formats with the same fourcc on both sides,
> > > I don't see what good that would be since the formats we have now are
> > > still plagued by the inconsistency.
> > >
> > > I think we always need an explicit translation step from either v4l2 or
> > > drm to the internal representation and back, without ever assuming that
> > > formats might be compatible because they share the same fourcc.
> >
> > I don't agree. APIs evolve, and while we can't switch from one set of
> > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > be impopular from a userspace developers point of view there, I don't
> > think we have ruled it out completely. The move to the request API is
> > also an area where a common set of 4CCs could be used, as it will depart
> > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > yet, but I wouldn't rule it out completely for the future.
> >
> > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > modifier.
> >
> > DRM modifiers are mostly about tiling and compression, and we hardly
> > support these in V4L2. What are the modifiers you think are hardcoded in
> > 4CCs in V4L2 ?
>
> Hm maybe it was a drm one that didn't come from v4l or anywhere else
> really, but the NV12MT one is nv12 + some tiling. I think we managed to
> uapi-bend that one into shape in at least drm.

The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
pretty similar case to the Mediatek one indeed.

In our cause, that's because the video decoding engine produces its
destination buffers in a specific tiled format, that the display engine
can take in directly.

Cheers,

Paul

> -Daniel
>
> > > I think Boris (CCed) is working to change that by allowing to
> > > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > > where some formats are described by the v4l2 pixfmt alone and some
> > > formats are also described a modifier (but I looked at it from a
> > > distance so might have misunderstod). That feels better since it avoids
> > > the combinatory explosion from describing each format + modifier
> > > individually.
> > >
> > > What do you think?
> > >
> > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > in modifiers a lot more.
> > > >
> > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > >
> > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > valid as ever:
> > > > >
> > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > >
> > > > Do yo have an example of one of those areas?
> > > >
> > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > e.g. offset for planar yuv formats, or tiling mode
> > > >
> > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > what DRM is doing.
> > > >
> > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > uniquely, drivers can override that (that's an explicit design
> > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > e.g. compression information). You'd need to pull that driver
> > > > > knowledge into your format library.
> > > >
> > > > I'm not sure how my patches are changing anything here. This is
> > > > litterally the same code, with the functions renamed.
> > > >
> > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > that. Just like any helper this just provides a default that covers
> > > > most of the cases.
> > > >
> > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > something like a new addfb flag.
> > > >
> > > > For the formats that would be described as a modifier, sure. For all
> > > > the others (that are not yet supported by DRM), then I don't really
> > > > see why not.
> > > >
> > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > >
> > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > since it will be easy to discover the formats that are already
> > > > > > supported by the other subsystem.
> > > > >
> > > > > I think a compat library that (tries to, best effort) convert between
> > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > perhaps. That should be useful for drivers.
> > > >
> > > > That's not really what this series is about though. That series is
> > > > about sharing the (image|pixels) formats database across everyone so
> > > > that everyone can benefit from it.
> > > >
> > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > drm_fourcc a few years back.
> > > > >
> > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > then:
> > > > > >
> > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > would work.
> > > > >
> > > > > Well, if we end up with a common library then yes we need cross
> > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > they get cross-posted is easy. No file renaming needed.
> > > >
> > > > That would create some governing issues as well. For example, if you
> > > > ever have a patch from one fourcc addition (that might or might not be
> > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > >
> > > > If it's shared code, then it should be shared, and every client
> > > > framework put on an equal footing.
> > > >
> > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > solution, since the information would be greatly duplicated
> > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > size that would be duplicated too.
> > > > >
> > > > > It's essentially what we decided to do for drm years back.
> > > >
> > > > And it was probably the right solution back then, but I'm really not
> > > > convinced it's still the right thing to do today.
> > > >
> > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > centralized.
> > > > >
> > > > > What I think could work as middle ground:
> > > > > - Put drm_format stuff into a separate .ko
> > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > and v4l formats. On the drm side that most likely means you need
> > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > the drivers that use this library need.
> > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > format space.
> > > > >
> > > > > Forcing this unification on everyone otoh is imo way too much.
> > > >
> > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > pretty much untouched for that library, so I'm not really sure how
> > > > anyone is hurt by that unification.
> >
> > --
> > Regards,
> >
> > Laurent Pinchart
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-23 14:29:52

by Nicolas Dufresne

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Le mardi 23 avril 2019 à 14:33 +0200, Paul Kocialkowski a écrit :
> Hi,
>
> On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> > On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > > Hi Paul,
> > >
> > > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > really it's totally not.
> > > > >
> > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > >
> > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > for the fourcc, so it definitely looks like a standard to me.
> > > >
> > > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > > cause, as it has already significantly diverged. Even if we coordinate
> > > > an effort to introduce new formats with the same fourcc on both sides,
> > > > I don't see what good that would be since the formats we have now are
> > > > still plagued by the inconsistency.
> > > >
> > > > I think we always need an explicit translation step from either v4l2 or
> > > > drm to the internal representation and back, without ever assuming that
> > > > formats might be compatible because they share the same fourcc.
> > >
> > > I don't agree. APIs evolve, and while we can't switch from one set of
> > > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > > be impopular from a userspace developers point of view there, I don't
> > > think we have ruled it out completely. The move to the request API is
> > > also an area where a common set of 4CCs could be used, as it will depart
> > > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > > yet, but I wouldn't rule it out completely for the future.
> > >
> > > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > > modifier.
> > >
> > > DRM modifiers are mostly about tiling and compression, and we hardly
> > > support these in V4L2. What are the modifiers you think are hardcoded in
> > > 4CCs in V4L2 ?
> >
> > Hm maybe it was a drm one that didn't come from v4l or anywhere else
> > really, but the NV12MT one is nv12 + some tiling. I think we managed to
> > uapi-bend that one into shape in at least drm.
>
> The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
> to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
> pretty similar case to the Mediatek one indeed.
>
> In our cause, that's because the video decoding engine produces its
> destination buffers in a specific tiled format, that the display engine
> can take in directly.

We also have the Samsung tiling (Z pattern) as mentioned here, but also
linear 16x16 tile placement (also from Samsung ?) and I believe Amlogic
CODEC patches is bringing another tiling (unavoidable on older Meson8,
with 64bytes swaps). All these should be expressed as NV12 + mod in DRM
space.

What is very often not enabled, but affect the performance on mainline
media drivers is the ARM frame buffer compression. I know that RK chips
have support for this, and that you can't achieve the maximum
throughput without that. This one is not documented anywhere, but I
understand that there is multiple variants that HW vendor licence.
Though, in general, each SoC are likely running a single variant, so a
single mod would make sense.

So all this to say that V4L2 equally needs supports for these. What I
understood through DRM API is that a buffer allocated for let's say
NV12 + mod, is compatible with linear NV12. That could be used to
simplify some code, but at the same time, a common API that deals with
the padding and alignment of each format + mod independently would do
that same as long as this is not variable depending on which target HW
uses that same format.

I think DRM + mod reduce the amount of dedicated formats that needs to
be added, and simplify the documentation of each formats. I was looking
at the Amlogic Axi configurations on Amlogic S905x recently, and for
each well known format, there is a bitmask that let you do arbitrary
swapping of bits, so effectively if we start exposing all these with
V4L2 style, the list would become very long and hard to maintained.

>
> Cheers,
>
> Paul
>
> > -Daniel
> >
> > > > I think Boris (CCed) is working to change that by allowing to
> > > > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > > > where some formats are described by the v4l2 pixfmt alone and some
> > > > formats are also described a modifier (but I looked at it from a
> > > > distance so might have misunderstod). That feels better since it avoids
> > > > the combinatory explosion from describing each format + modifier
> > > > individually.
> > > >
> > > > What do you think?
> > > >
> > > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > > in modifiers a lot more.
> > > > >
> > > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > > >
> > > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > > valid as ever:
> > > > > >
> > > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > > >
> > > > > Do yo have an example of one of those areas?
> > > > >
> > > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > > e.g. offset for planar yuv formats, or tiling mode
> > > > >
> > > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > > what DRM is doing.
> > > > >
> > > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > > uniquely, drivers can override that (that's an explicit design
> > > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > > e.g. compression information). You'd need to pull that driver
> > > > > > knowledge into your format library.
> > > > >
> > > > > I'm not sure how my patches are changing anything here. This is
> > > > > litterally the same code, with the functions renamed.
> > > > >
> > > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > > that. Just like any helper this just provides a default that covers
> > > > > most of the cases.
> > > > >
> > > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > > something like a new addfb flag.
> > > > >
> > > > > For the formats that would be described as a modifier, sure. For all
> > > > > the others (that are not yet supported by DRM), then I don't really
> > > > > see why not.
> > > > >
> > > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > > >
> > > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > > since it will be easy to discover the formats that are already
> > > > > > > supported by the other subsystem.
> > > > > >
> > > > > > I think a compat library that (tries to, best effort) convert between
> > > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > > perhaps. That should be useful for drivers.
> > > > >
> > > > > That's not really what this series is about though. That series is
> > > > > about sharing the (image|pixels) formats database across everyone so
> > > > > that everyone can benefit from it.
> > > > >
> > > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > > drm_fourcc a few years back.
> > > > > >
> > > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > > then:
> > > > > > >
> > > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > > would work.
> > > > > >
> > > > > > Well, if we end up with a common library then yes we need cross
> > > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > > they get cross-posted is easy. No file renaming needed.
> > > > >
> > > > > That would create some governing issues as well. For example, if you
> > > > > ever have a patch from one fourcc addition (that might or might not be
> > > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > > >
> > > > > If it's shared code, then it should be shared, and every client
> > > > > framework put on an equal footing.
> > > > >
> > > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > > solution, since the information would be greatly duplicated
> > > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > > size that would be duplicated too.
> > > > > >
> > > > > > It's essentially what we decided to do for drm years back.
> > > > >
> > > > > And it was probably the right solution back then, but I'm really not
> > > > > convinced it's still the right thing to do today.
> > > > >
> > > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > > centralized.
> > > > > >
> > > > > > What I think could work as middle ground:
> > > > > > - Put drm_format stuff into a separate .ko
> > > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > > and v4l formats. On the drm side that most likely means you need
> > > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > > the drivers that use this library need.
> > > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > > format space.
> > > > > >
> > > > > > Forcing this unification on everyone otoh is imo way too much.
> > > > >
> > > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > > pretty much untouched for that library, so I'm not really sure how
> > > > > anyone is hurt by that unification.
> > >
> > > --
> > > Regards,
> > >
> > > Laurent Pinchart


Attachments:
signature.asc (201.00 B)
This is a digitally signed message part

2019-04-23 14:57:55

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

On Tue, 2019-04-23 at 10:28 -0400, Nicolas Dufresne wrote:
> Le mardi 23 avril 2019 à 14:33 +0200, Paul Kocialkowski a écrit :
> > Hi,
> >
> > On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> > > On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > > > Hi Paul,
> > > >
> > > > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > > really it's totally not.
> > > > > >
> > > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > > >
> > > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > > for the fourcc, so it definitely looks like a standard to me.
> > > > >
> > > > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > > > cause, as it has already significantly diverged. Even if we coordinate
> > > > > an effort to introduce new formats with the same fourcc on both sides,
> > > > > I don't see what good that would be since the formats we have now are
> > > > > still plagued by the inconsistency.
> > > > >
> > > > > I think we always need an explicit translation step from either v4l2 or
> > > > > drm to the internal representation and back, without ever assuming that
> > > > > formats might be compatible because they share the same fourcc.
> > > >
> > > > I don't agree. APIs evolve, and while we can't switch from one set of
> > > > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > > > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > > > be impopular from a userspace developers point of view there, I don't
> > > > think we have ruled it out completely. The move to the request API is
> > > > also an area where a common set of 4CCs could be used, as it will depart
> > > > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > > > yet, but I wouldn't rule it out completely for the future.
> > > >
> > > > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > > > modifier.
> > > >
> > > > DRM modifiers are mostly about tiling and compression, and we hardly
> > > > support these in V4L2. What are the modifiers you think are hardcoded in
> > > > 4CCs in V4L2 ?
> > >
> > > Hm maybe it was a drm one that didn't come from v4l or anywhere else
> > > really, but the NV12MT one is nv12 + some tiling. I think we managed to
> > > uapi-bend that one into shape in at least drm.
> >
> > The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
> > to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
> > pretty similar case to the Mediatek one indeed.
> >
> > In our cause, that's because the video decoding engine produces its
> > destination buffers in a specific tiled format, that the display engine
> > can take in directly.
>
> We also have the Samsung tiling (Z pattern) as mentioned here, but also
> linear 16x16 tile placement (also from Samsung ?) and I believe Amlogic
> CODEC patches is bringing another tiling (unavoidable on older Meson8,
> with 64bytes swaps). All these should be expressed as NV12 + mod in DRM
> space.
>
> What is very often not enabled, but affect the performance on mainline
> media drivers is the ARM frame buffer compression. I know that RK chips
> have support for this, and that you can't achieve the maximum
> throughput without that. This one is not documented anywhere, but I
> understand that there is multiple variants that HW vendor licence.
> Though, in general, each SoC are likely running a single variant, so a
> single mod would make sense.
>
> So all this to say that V4L2 equally needs supports for these.

Yes, I definitely agree with that.

> What I understood through DRM API is that a buffer allocated for let's say
> NV12 + mod, is compatible with linear NV12. That could be used to
> simplify some code, but at the same time, a common API that deals with
> the padding and alignment of each format + mod independently would do
> that same as long as this is not variable depending on which target HW
> uses that same format.
>
> I think DRM + mod reduce the amount of dedicated formats that needs to
> be added, and simplify the documentation of each formats. I was looking
> at the Amlogic Axi configurations on Amlogic S905x recently, and for
> each well known format, there is a bitmask that let you do arbitrary
> swapping of bits, so effectively if we start exposing all these with
> V4L2 style, the list would become very long and hard to maintained.

The number of possible combinations is indeed much too high to have
them exposed as single V4L2 formats. Not to mention the VC4 tiling
modifiers where the column height is passed as an argument to the
modifier (so there is a modifier base and a variable part to it).

So I definitely agree that having a way to represent modifiers in V4L2
would be quite relevant and useful.

Cheers,

Paul

> > > -Daniel
> > >
> > > > > I think Boris (CCed) is working to change that by allowing to
> > > > > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > > > > where some formats are described by the v4l2 pixfmt alone and some
> > > > > formats are also described a modifier (but I looked at it from a
> > > > > distance so might have misunderstod). That feels better since it avoids
> > > > > the combinatory explosion from describing each format + modifier
> > > > > individually.
> > > > >
> > > > > What do you think?
> > > > >
> > > > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > > > in modifiers a lot more.
> > > > > >
> > > > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > > > >
> > > > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > > > valid as ever:
> > > > > > >
> > > > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > > > >
> > > > > > Do yo have an example of one of those areas?
> > > > > >
> > > > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > > > e.g. offset for planar yuv formats, or tiling mode
> > > > > >
> > > > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > > > what DRM is doing.
> > > > > >
> > > > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > > > uniquely, drivers can override that (that's an explicit design
> > > > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > > > e.g. compression information). You'd need to pull that driver
> > > > > > > knowledge into your format library.
> > > > > >
> > > > > > I'm not sure how my patches are changing anything here. This is
> > > > > > litterally the same code, with the functions renamed.
> > > > > >
> > > > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > > > that. Just like any helper this just provides a default that covers
> > > > > > most of the cases.
> > > > > >
> > > > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > > > something like a new addfb flag.
> > > > > >
> > > > > > For the formats that would be described as a modifier, sure. For all
> > > > > > the others (that are not yet supported by DRM), then I don't really
> > > > > > see why not.
> > > > > >
> > > > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > > > >
> > > > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > > > since it will be easy to discover the formats that are already
> > > > > > > > supported by the other subsystem.
> > > > > > >
> > > > > > > I think a compat library that (tries to, best effort) convert between
> > > > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > > > perhaps. That should be useful for drivers.
> > > > > >
> > > > > > That's not really what this series is about though. That series is
> > > > > > about sharing the (image|pixels) formats database across everyone so
> > > > > > that everyone can benefit from it.
> > > > > >
> > > > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > > > drm_fourcc a few years back.
> > > > > > >
> > > > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > > > then:
> > > > > > > >
> > > > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > > > would work.
> > > > > > >
> > > > > > > Well, if we end up with a common library then yes we need cross
> > > > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > > > they get cross-posted is easy. No file renaming needed.
> > > > > >
> > > > > > That would create some governing issues as well. For example, if you
> > > > > > ever have a patch from one fourcc addition (that might or might not be
> > > > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > > > >
> > > > > > If it's shared code, then it should be shared, and every client
> > > > > > framework put on an equal footing.
> > > > > >
> > > > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > > > solution, since the information would be greatly duplicated
> > > > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > > > size that would be duplicated too.
> > > > > > >
> > > > > > > It's essentially what we decided to do for drm years back.
> > > > > >
> > > > > > And it was probably the right solution back then, but I'm really not
> > > > > > convinced it's still the right thing to do today.
> > > > > >
> > > > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > > > centralized.
> > > > > > >
> > > > > > > What I think could work as middle ground:
> > > > > > > - Put drm_format stuff into a separate .ko
> > > > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > > > and v4l formats. On the drm side that most likely means you need
> > > > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > > > the drivers that use this library need.
> > > > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > > > format space.
> > > > > > >
> > > > > > > Forcing this unification on everyone otoh is imo way too much.
> > > > > >
> > > > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > > > pretty much untouched for that library, so I'm not really sure how
> > > > > > anyone is hurt by that unification.
> > > >
> > > > --
> > > > Regards,
> > > >
> > > > Laurent Pinchart
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

2019-04-23 15:11:22

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Tue, Apr 23, 2019 at 4:28 PM Nicolas Dufresne <[email protected]> wrote:
>
> Le mardi 23 avril 2019 à 14:33 +0200, Paul Kocialkowski a écrit :
> > Hi,
> >
> > On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> > > On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > > > Hi Paul,
> > > >
> > > > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > > really it's totally not.
> > > > > >
> > > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > > >
> > > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > > for the fourcc, so it definitely looks like a standard to me.
> > > > >
> > > > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > > > cause, as it has already significantly diverged. Even if we coordinate
> > > > > an effort to introduce new formats with the same fourcc on both sides,
> > > > > I don't see what good that would be since the formats we have now are
> > > > > still plagued by the inconsistency.
> > > > >
> > > > > I think we always need an explicit translation step from either v4l2 or
> > > > > drm to the internal representation and back, without ever assuming that
> > > > > formats might be compatible because they share the same fourcc.
> > > >
> > > > I don't agree. APIs evolve, and while we can't switch from one set of
> > > > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > > > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > > > be impopular from a userspace developers point of view there, I don't
> > > > think we have ruled it out completely. The move to the request API is
> > > > also an area where a common set of 4CCs could be used, as it will depart
> > > > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > > > yet, but I wouldn't rule it out completely for the future.
> > > >
> > > > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > > > modifier.
> > > >
> > > > DRM modifiers are mostly about tiling and compression, and we hardly
> > > > support these in V4L2. What are the modifiers you think are hardcoded in
> > > > 4CCs in V4L2 ?
> > >
> > > Hm maybe it was a drm one that didn't come from v4l or anywhere else
> > > really, but the NV12MT one is nv12 + some tiling. I think we managed to
> > > uapi-bend that one into shape in at least drm.
> >
> > The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
> > to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
> > pretty similar case to the Mediatek one indeed.
> >
> > In our cause, that's because the video decoding engine produces its
> > destination buffers in a specific tiled format, that the display engine
> > can take in directly.
>
> We also have the Samsung tiling (Z pattern) as mentioned here, but also
> linear 16x16 tile placement (also from Samsung ?) and I believe Amlogic
> CODEC patches is bringing another tiling (unavoidable on older Meson8,
> with 64bytes swaps). All these should be expressed as NV12 + mod in DRM
> space.
>
> What is very often not enabled, but affect the performance on mainline
> media drivers is the ARM frame buffer compression. I know that RK chips
> have support for this, and that you can't achieve the maximum
> throughput without that. This one is not documented anywhere, but I
> understand that there is multiple variants that HW vendor licence.
> Though, in general, each SoC are likely running a single variant, so a
> single mod would make sense.

We have AFBC modifiers now in drm_fourcc.h, jointly developed by
display engineers from ARM and mali gpu reverse engineer people doing
the panfrost driver. So should be covered.

> So all this to say that V4L2 equally needs supports for these. What I
> understood through DRM API is that a buffer allocated for let's say
> NV12 + mod, is compatible with linear NV12. That could be used to
> simplify some code, but at the same time, a common API that deals with
> the padding and alignment of each format + mod independently would do
> that same as long as this is not variable depending on which target HW
> uses that same format.

Not sure why you mean with NV12 + mod is compatible with linear NV12.
In general fourcc + modifier != fourcc = linear modifier, size, number
of planes, alignment constraints and everything else can be changed by
a modifier (and there's examples for all of these, maybe not yet in
all cases for NV12, but I think NV12 + AFBC modifiers gives some
pretty interesting results). In generally you need to think of the
(drm fourcc, modifier) as the pair identified the pixel format, each
part individually is fairly meanigless. We have lots of modifiers
where the exact tiling mode/layout changes depending upon the fourcc
code.

The only exception is legacy interfaces, i.e. when you create a
framebuffer with only the drm fourcc and not a modifier. In that case
you get driver specific behaviour, but modifier aware drivers tend to
change that into a specific (fourcc, modifier) pair again (at least
i915.ko, and it's what I recommend).

Oh and we have some legacy modifiers that depend upon the target hw,
but it's very much not recommended (we did it in i915 to make things
easier on really old platforms, on some of them we don't even know the
exact tiling mode since it's not documented nor correctly
reverse-engineered).

Another fun case are some of the recent non-byte-aligned formats, for
which you need to have a modifier to be able to use them with anything
- there's not really a real linear layout for them, they just serve as
an index/parameter into the modifier space.

> I think DRM + mod reduce the amount of dedicated formats that needs to
> be added, and simplify the documentation of each formats. I was looking
> at the Amlogic Axi configurations on Amlogic S905x recently, and for
> each well known format, there is a bitmask that let you do arbitrary
> swapping of bits, so effectively if we start exposing all these with
> V4L2 style, the list would become very long and hard to maintained.

See above, modifiers aren't really simple ...
-Daniel

> >
> > Cheers,
> >
> > Paul
> >
> > > -Daniel
> > >
> > > > > I think Boris (CCed) is working to change that by allowing to
> > > > > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > > > > where some formats are described by the v4l2 pixfmt alone and some
> > > > > formats are also described a modifier (but I looked at it from a
> > > > > distance so might have misunderstod). That feels better since it avoids
> > > > > the combinatory explosion from describing each format + modifier
> > > > > individually.
> > > > >
> > > > > What do you think?
> > > > >
> > > > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > > > in modifiers a lot more.
> > > > > >
> > > > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > > > >
> > > > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > > > valid as ever:
> > > > > > >
> > > > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > > > >
> > > > > > Do yo have an example of one of those areas?
> > > > > >
> > > > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > > > e.g. offset for planar yuv formats, or tiling mode
> > > > > >
> > > > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > > > what DRM is doing.
> > > > > >
> > > > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > > > uniquely, drivers can override that (that's an explicit design
> > > > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > > > e.g. compression information). You'd need to pull that driver
> > > > > > > knowledge into your format library.
> > > > > >
> > > > > > I'm not sure how my patches are changing anything here. This is
> > > > > > litterally the same code, with the functions renamed.
> > > > > >
> > > > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > > > that. Just like any helper this just provides a default that covers
> > > > > > most of the cases.
> > > > > >
> > > > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > > > something like a new addfb flag.
> > > > > >
> > > > > > For the formats that would be described as a modifier, sure. For all
> > > > > > the others (that are not yet supported by DRM), then I don't really
> > > > > > see why not.
> > > > > >
> > > > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > > > >
> > > > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > > > since it will be easy to discover the formats that are already
> > > > > > > > supported by the other subsystem.
> > > > > > >
> > > > > > > I think a compat library that (tries to, best effort) convert between
> > > > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > > > perhaps. That should be useful for drivers.
> > > > > >
> > > > > > That's not really what this series is about though. That series is
> > > > > > about sharing the (image|pixels) formats database across everyone so
> > > > > > that everyone can benefit from it.
> > > > > >
> > > > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > > > drm_fourcc a few years back.
> > > > > > >
> > > > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > > > then:
> > > > > > > >
> > > > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > > > would work.
> > > > > > >
> > > > > > > Well, if we end up with a common library then yes we need cross
> > > > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > > > they get cross-posted is easy. No file renaming needed.
> > > > > >
> > > > > > That would create some governing issues as well. For example, if you
> > > > > > ever have a patch from one fourcc addition (that might or might not be
> > > > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > > > >
> > > > > > If it's shared code, then it should be shared, and every client
> > > > > > framework put on an equal footing.
> > > > > >
> > > > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > > > solution, since the information would be greatly duplicated
> > > > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > > > size that would be duplicated too.
> > > > > > >
> > > > > > > It's essentially what we decided to do for drm years back.
> > > > > >
> > > > > > And it was probably the right solution back then, but I'm really not
> > > > > > convinced it's still the right thing to do today.
> > > > > >
> > > > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > > > centralized.
> > > > > > >
> > > > > > > What I think could work as middle ground:
> > > > > > > - Put drm_format stuff into a separate .ko
> > > > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > > > and v4l formats. On the drm side that most likely means you need
> > > > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > > > the drivers that use this library need.
> > > > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > > > format space.
> > > > > > >
> > > > > > > Forcing this unification on everyone otoh is imo way too much.
> > > > > >
> > > > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > > > pretty much untouched for that library, so I'm not really sure how
> > > > > > anyone is hurt by that unification.
> > > >
> > > > --
> > > > Regards,
> > > >
> > > > Laurent Pinchart



--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-04-23 15:47:03

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Daniel,

On Tue, Apr 23, 2019 at 09:25:54AM +0200, Daniel Vetter wrote:
> On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> > On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> >> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> >>> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> >>>> On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> >>>>> On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> >>>>>> On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> >>>>>>> Hi,
> >>>>>>>
> >>>>>>> DRM comes with an extensive format support to retrieve the various
> >>>>>>> parameters associated with a given format (such as the subsampling, or the
> >>>>>>> bits per pixel), as well as some helpers and utilities to ease the driver
> >>>>>>> development.
> >>>>>>>
> >>>>>>> v4l2, on the other side, doesn't provide such facilities, leaving each
> >>>>>>> driver reimplement a subset of the formats parameters for the one supported
> >>>>>>> by that particular driver. This leads to a lot of duplication and
> >>>>>>> boilerplate code in the v4l2 drivers.
> >>>>>>>
> >>>>>>> This series tries to address this by moving the DRM format API into lib and
> >>>>>>> turning it into a more generic API. In order to do this, we've needed to do
> >>>>>>> some preliminary changes on the DRM drivers, then moved the API and finally
> >>>>>>> converted a v4l2 driver to give an example of how such library could be
> >>>>>>> used.
> >>>>>>>
> >>>>>>> Let me know what you think,
> >>>>>>> Maxime
> >>>>>>>
> >>>>>>> Changes from RFC:
> >>>>>>> - Rebased on next
> >>>>>>> - Fixed the various formats mapping
> >>>>>>> - Added tags
> >>>>>>> - Did most of the formats functions as inline functions
> >>>>>>> - Used a consistent prefix for all the utilities functions
> >>>>>>> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> >>>>>>> arm64 and x86_64
> >>>>>>> - Fixed out of array bounds warnings in the image_format_info_block_*
> >>>>>>> functions
> >>>>>>> - Added License and copyright headers on missing files
> >>>>>>>
> >>>>>>> Maxime Ripard (20):
> >>>>>>> drm: Remove users of drm_format_num_planes
> >>>>>>> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> >>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> >>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> >>>>>>> drm: Replace instances of drm_format_info by drm_get_format_info
> >>>>>>> lib: Add video format information library
> >>>>>>> drm/fb: Move from drm_format_info to image_format_info
> >>>>>>> drm/malidp: Convert to generic image format library
> >>>>>>> drm/client: Convert to generic image format library
> >>>>>>> drm/exynos: Convert to generic image format library
> >>>>>>> drm/i915: Convert to generic image format library
> >>>>>>> drm/ipuv3: Convert to generic image format library
> >>>>>>> drm/msm: Convert to generic image format library
> >>>>>>> drm/omap: Convert to generic image format library
> >>>>>>> drm/rockchip: Convert to generic image format library
> >>>>>>> drm/tegra: Convert to generic image format library
> >>>>>>> drm/fourcc: Remove old DRM format API
> >>>>>>> lib: image-formats: Add v4l2 formats support
> >>>>>>> lib: image-formats: Add more functions
> >>>>>>> media: sun6i: Convert to the image format API
> >>>>>>
> >>>>>> In the interest of making myself unpopular: Why move this out of drm?
> >>>>>>
> >>>>>> We do have a bunch of other such shared helpers already (mostly in
> >>>>>> drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> >>>>>> sure that's going better than keeping it maintained in drm.
> >
> > That's a bit of a different situation as both DRM and FBDEV address the
> > same features (display output), and FBDEV is deprecared and replaced by
> > DRM.
> >
> > I'm not against maintaining a 4CC library in DRM (adding a third-party
> > maintainer would likely create more problems than it would solve), but
> > that doesn't mean the library has to live in drivers/gpu/, nor that it
> > needs to have the drm_ prefix. I would actually advocate to make it live
> > in a neutral directory, with a neutral prefix (kudos to anyone who can
> > propose a nice naming convention that would establish a new shared
> > ground for image/video-related Linux APIs), and maintained through the
> > DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> > reaches all the related folks).
> >
> >>>>>> Plus the uapi is already that you include drm_fourcc.h to get at these,
> >>>>>> dropping the drm prefix isn't going to help I think.
> >>>>>>
> >>>>>> Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> >>>>>> use it without dragging in all of drm), and we need to add some fields for
> >>>>>> converting to v4l fourcc codes (which are different). But that should be
> >>>>>> all possible. And I don't think the drm_ prefix in v4l code is a problem,
> >>>>>> it's actually a feature: It makes it really clear that these are the drm
> >>>>>> fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> >>>>>> that. That allocation authority is also already baked into various khr/ext
> >>>>>> standards, too.
> >
> > There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> > documentation. Look at
> > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> > or
> > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> > for instance. It's painful to write, painful to read, but defines the
> > 4CCs very clearly without ambiguity. I wouldn't be surprised if
> > different drivers used the same DRM 4CC for different formats due to the
> > lack of detailed documentation. Moving to a shared library for 4CCs
> > should also address the documentation side, and any new format added to
> > the kernel, whether from the V4L2 side or the DRM side, would be
> > required to provide detailed documentation. That would be a great
> > improvement for DRM 4CC handling.
> >
> >>>>> The way I see it, there's a fundamental difference between the UAPI
> >>>>> and the kernel. I don't suggest we change anything about the UAPI: the
> >>>>> drm formats should keep their prefix, drm_fourcc.h can remain that
> >>>>> authority, it's all fine.
> >>>>>
> >>>>> Internally however, the long term goal is to share the fourcc's
> >>>>> between DRM and V4L2 for the same formats. It basically means that of
> >>>>> course v4l2 should be using the DRM fourcc when a format exists in DRM
> >>>>> and not v4l2, but also that DRM should use v4l2 fourcc when the format
> >>>>> exists in v4l2 but not DRM, and that is far more likely, given the
> >>>>> already extensive v4l2 formats support.
> >>>>
> >>>> Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> >>>> format identifier space.
> >>>
> >>> No to what exactly?
> >>>
> >>>> And a lot of people pushed for the "fourcc is a standard", when
> >>>> really it's totally not.
> >>>
> >>> Even if it's not a standard, having consistency would be a good thing.
> >>>
> >>> And you said yourself that DRM fourcc is now pretty much an authority
> >>> for the fourcc, so it definitely looks like a standard to me.
> >>
> >> drm fourcc is the authority for drm fourcc codes. Not for any of the
> >> others (and there's lots of them). Now it's used in a bunch of other
> >> places (khr standards, dri protocols in wayland/X11), but they're
> >> still only drm fourcc. There is no overall fourcc standard.
> >>
> >>>> v4l tends to conflate pixel format with stuff that we tend to encode
> >>>> in modifiers a lot more.
> >>>
> >>> Boris is working on adding the modifiers concept to v4l2, so we're
> >>> converging here, and we can totally have a layer in v4l2 to convert
> >>> between old v4l2 "format+modifiers" formats, and DRM style formats.
> >>>
> >>>> There's a bunch of reasons we can't just use v4l, and they're as
> >>>> valid as ever:
> >>>>
> >>>> - We overlap badly in some areas, so even if fourcc codes match, we
> >>>> can't use them and need a duplicated DRM_FOURCC code.
> >>>
> >>> Do yo have an example of one of those areas?
> >>
> >> I think the rgb stuff was one of the big reasons to not reuse any
> >> existing fourcc standard (whether v4l, or another one from e.g. video
> >> container formats). We had initial patches to reuse the fourcc that
> >> existed, but the end result was really inconsistent, so we ditch that
> >> and rolled out a new set of entirely drm specific fourcc codes for
> >> rgba.
> >
> > Could you give one or a couple of examples of V4L2 4CCs that are not
> > OCD-compatible ? :-)
> >
> >>>> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> >>>> e.g. offset for planar yuv formats, or tiling mode
> >>>
> >>> As I was saying, this changes on the v4l2 side, and converging to
> >>> what DRM is doing.
> >>>
> >>>> - drm fourcc code doesn't actually define the drm_format_info
> >>>> uniquely, drivers can override that (that's an explicit design
> >>>> intent of modifiers, to allow drivers to add another plane for
> >>>> e.g. compression information). You'd need to pull that driver
> >>>> knowledge into your format library.
> >
> > That's a mistake in my opinion. We tried that in V4L2 to store metadata
> > in a separate plane, and had to go another route eventually as it
> > created a very bad mess.
>
> Just quick clarification in the middle here: This is how the hw works.

The hardware takes parameters from a buffer, but it doesn't mandate how
that buffer is exposed to userspace :-) Using an extra plane is one
option, but other APIs are possible.

> It's not metadata that sw ever touches (in general, testcases to make sure
> we display these correctly excepted).
>
> There has been some talking to add maybe a bit more mixed metadata, for
> fast-clear colors (which isn't used by any display engine afaik yet). That

What are fast-clear colors ?

> would generally be written by the cpu (in the gl stack), but again read by
> the hw (loaded as indirect state packet most likely, or something like
> that). So again hw specific layout, because the hw needs to read it.
>
> Pure metadata only of interest for the cpu/sw stack has been shot down
> completely on the drm side too.
>
> > There's a tendency in both subsystems to look at the other as a bit of a
> > retarded relative, and that's a shame, we have lots to learn from each
> > other's mistakes. That wouldn't be too difficult if people started
> > talking to each other.
> >
> > A semi-related comment: DRM also carries other mistakes of its own, I'm
> > thinking about DRM_FORMAT_BIG_ENDIAN in particular
>
> Yeah that one is hilarios, but in practice big endian is dead, except for
> a very few server chips, and there I think Gerd's work mostly fixed up
> that mess.
>
> >>> I'm not sure how my patches are changing anything here. This is
> >>> litterally the same code, with the functions renamed.
> >>>
> >>> If drivers want to override that, then yeah, fine, we can let them do
> >>> that. Just like any helper this just provides a default that covers
> >>> most of the cases.
> >>>
> >>>> Iow there's no way we can easily adopt v4l fourcc, except if we do
> >>>> something like a new addfb flag.
> >>>
> >>> For the formats that would be described as a modifier, sure. For all
> >>> the others (that are not yet supported by DRM), then I don't really
> >>> see why not.
> >>
> >> See above, we tried that initially, didn't pass the ocd tests when
> >> reviewing. Maybe the situation is better outside of rbgx/a formats,
> >> and I think we do at least try to use the same fourcc codes there when
> >> there already is one. But then the details occasionally look
> >> different.
> >>
> >>>>> And given how the current state is a mess in this regard, I'm not too
> >>>>> optimistic about keeping the formats in their relevant frameworks.
> >>>>>
> >>>>> Having a shared library, governed by both, will make this far easier,
> >>>>> since it will be easy to discover the formats that are already
> >>>>> supported by the other subsystem.
> >>>>
> >>>> I think a compat library that (tries to, best effort) convert between
> >>>> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> >>>> to the conversion functions for videomode <-> drm_display_mode
> >>>> perhaps. That should be useful for drivers.
> >>>
> >>> That's not really what this series is about though. That series is
> >>> about sharing the (image|pixels) formats database across everyone so
> >>> that everyone can benefit from it.
> >>
> >> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> >> would be good, since there's really no standard here.
> >>
> >>>> Unifying the formats themselves, and all the associated metadata is
> >>>> imo a no-go, and was a pretty conscious decision when we implemented
> >>>> drm_fourcc a few years back.
> >>>>
> >>>>> If we want to keep the current library in DRM, we have two options
> >>>>> then:
> >>>>>
> >>>>> - Support all the v4l2 formats in the DRM library, which is
> >>>>> essentially what I'm doing in the last patches. However, that
> >>>>> would require to have the v4l2 developpers also reviewing stuff
> >>>>> there. And given how busy they are, I cannot really see how that
> >>>>> would work.
> >>>>
> >>>> Well, if we end up with a common library then yes we need cross
> >>>> review. There's no way around that. Doesn't matter where exactly that
> >>>> library is in the filesystem tree, and adding a special MAINTAINERS
> >>>> entry for anything related to fourcc (both drm and v4l) to make sure
> >>>> they get cross-posted is easy. No file renaming needed.
> >>>
> >>> That would create some governing issues as well. For example, if you
> >>> ever have a patch from one fourcc addition (that might or might not be
> >>> covered by v4l2), will you wait for any v4l2 developper to review it?
> >>
> >> None of this is fixed by code renaming or locations. Either way we
> >> need to figure that out.
> >>
> >> And yes part of the reasons for not moving this out of drm is that I'm
> >> not a fan of boutique trees for small stuff. If sharing means we need
> >> to split the drm_fourcc code and library out of drm trees, I'm not
> >> sure that's a good idea. We're already super liberal with merging
> >> anything through driver trees with acks, and integrating them quickly
> >> into drm-next. This would still be workable if v4l sends regular pull
> >> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> >> do). If we can only sync up once per merge window with a shared
> >> boutique tree for formats only, life is going to be painful.
> >
> > That should be solved by the proposal above, maintaining the shared
> > library in the DRM tree. We would need to be careful there, and ideally
> > maintain that in a separate branch that could be merged in both DRM and
> > V4L2 without having to merge most of the other subsystem's pending
> > changes at the same time, but I think it's doable without any big issue.
> >
> >>> If it's shared code, then it should be shared, and every client
> >>> framework put on an equal footing.
> >>>
> >>>>> - Develop the same library from within v4l2. That is really a poor
> >>>>> solution, since the information would be greatly duplicated
> >>>>> between the two, and in terms of maintainance, code, and binary
> >>>>> size that would be duplicated too.
> >>>>
> >>>> It's essentially what we decided to do for drm years back.
> >>>
> >>> And it was probably the right solution back then, but I'm really not
> >>> convinced it's still the right thing to do today.
> >>>
> >>>>> Having it shared allows to easily share, and discover formats from the
> >>>>> other subsystem, and to have a single, unique place where this is
> >>>>> centralized.
> >>>>
> >>>> What I think could work as middle ground:
> >>>> - Put drm_format stuff into a separate .ko
> >>>> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> >>>> posted to both drm and v4l lists. Easy on the drm side, since it's all
> >>>> separate files. Not sure it's so convenient for v4l uapi.
> >>>> - Add a conversion library that tries to best-effort map between drm
> >>>> and v4l formats. On the drm side that most likely means you need
> >>>> offsets for planes, and modifiers too (since those are implied in some
> >>>> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> >>>> the drivers that use this library need.
> >>>> - Add drm_fourcc as-needed by these drivers that want to use a unified
> >>>> format space.
> >>>>
> >>>> Forcing this unification on everyone otoh is imo way too much.
> >>>
> >>> v4l2 is starting to converge with DRM, and we're using the DRM API
> >>> pretty much untouched for that library, so I'm not really sure how
> >>> anyone is hurt by that unification.
> >>
> >> It might make sense to regularly pull v4l updates into drm-next then
> >> anyway. That would also remove the need to have the format library
> >> somewhere else.
> >
> > Are you saying it should the live in V4L2 ? ;-)
>
> Maybe a few clarifications on how the drm shared core thing usually works,
> and why I'm a sticker here. Bottom reply since I'm not sure where to put
> it:
>
> - Refactorings usually go in through drm-misc (at least since a few
> years).
>
> - Small patches go in through the relevant driver tree (which is often
> drm-misc, but not always), with an Ack from drm maintainers.
>
> - No topic branches, everyone just pushes patches where it's most
> convenient.
>
> We get away with this mess because everyone sends regular pull requests to
> drm, where the entire history is baked in and others can backmerge/fast
> forward/rebase. Worst case you wait one month (around the merge window,
> when drm-next is closed for features), but usually it's just 1-2 weeks.
> Plus we tend to have fairly big trees, with good chances that the next
> patch series lands in the same tree again and no work at all is needed.
>
> If we start regularly sharing lots of code with v4l (which seems to be the
> long term goal here), then I think we need something equally convenient
> for all that.
>
> We're not going to be able to teach some complicated topic branch scheme
> to the 50+ submaintainers/committers we have in drm - a lot much more
> basic stuff already takes lots of work to get it to stick. If the proposal
> is "to be careful" and "maintain it in a separate branch", I'm not in
> favour because I think that just wouldn't work.

Why not ? It can be a fast-moving branch that gets merged in drm-misc
as often as you want (even at every commit if that's desired). We're
dealing with a limited amount of code here, and there's no more reason
that V4L2 should pull in drm-misc to get 4CC updates than DRM should
pull V4L2 for the same. I have no objection against a 4CC branch being
officially maintained under the DRM umbrella, but I think the code
should live elsewhere than drivers/gpu/drm/, have a neutral prefix, and
not require pulling an entire subsystem in.


--
Regards,

Laurent Pinchart

2019-04-23 15:55:39

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Daniel,

On Tue, Apr 23, 2019 at 09:59:37AM +0100, Daniel Stone wrote:
> On Tue, 23 Apr 2019 at 08:26, Daniel Vetter <[email protected]> wrote:
> > On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> >>>>> - drm fourcc code doesn't actually define the drm_format_info
> >>>>> uniquely, drivers can override that (that's an explicit design
> >>>>> intent of modifiers, to allow drivers to add another plane for
> >>>>> e.g. compression information). You'd need to pull that driver
> >>>>> knowledge into your format library.
> >>
> >> That's a mistake in my opinion. We tried that in V4L2 to store metadata
> >> in a separate plane, and had to go another route eventually as it
> >> created a very bad mess.
> >
> > Just quick clarification in the middle here: This is how the hw works.
> > It's not metadata that sw ever touches (in general, testcases to make sure
> > we display these correctly excepted).
> >
> > There has been some talking to add maybe a bit more mixed metadata, for
> > fast-clear colors (which isn't used by any display engine afaik yet). That
> > would generally be written by the cpu (in the gl stack), but again read by
> > the hw (loaded as indirect state packet most likely, or something like
> > that). So again hw specific layout, because the hw needs to read it.
> >
> > Pure metadata only of interest for the cpu/sw stack has been shot down
> > completely on the drm side too.
>
> Totally. Let's take DRM_FORMAT_XRGB8888 + I915_FORMAT_MOD_Y_TILED as
> an example. Here, there is one colour plane which is laid out in a
> documented tiled format, containing normal XRGB8888 pixels once you do
> the maths to get the correct pixel location. So that's fine.
>
> I915_FORMAT_MOD_Y_TILED_CCS has a base colour plane as above, but adds
> an auxiliary plane which has a few bits describing the state of every
> (differently-sized) tile. Before reading the tile from the colour
> plane, you look at the corresponding location in the auxiliary plane:
> if you read 0x55 from the auxiliary plane, then the entire cacheline
> is the value of the first pixel, i.e. a solid fill. Hardware takes
> advantage of this to only write out the first pixel: if you try to
> read the colour plane as Y_TILED then for solid-filled regions, only
> the first pixel of every tile will show correctly, and the rest will
> be garbage.
>
> The auxiliary plane has its own layout and placement requirements, so
> we need to carry around an offset and a stride for the auxiliary data.
> We already have this for multiple planes; stuffing it into the base
> plane would require us to reinvent the same for auxiliary data within
> a single plane.

Looks like we have different kinds of metadata to consider. On the V4L2
side metadata usually refers to the context in which a frame was
captured, it doesn't tell how to interpret the contents of the pixels.
In the case you just described, the metadata is part of the frame
contents. I agree that this is a proper use case for storing such
metadata in a plane. What I wouldn't like to see being stored in a plane
is for instance gamma tables or similar data that configures the
processing pipeline in the display engine (I know we have an API for
gamma tables, this is just an example).

> I understand at least one of the Tegra colour-compression layouts (for
> Tegra 1xx?) is similar to this.
>
> It would be good to understand what you had in mind when you said that
> using multiple planes created a mess. I haven't touched media
> encode/decode units at a low level for quite a while (hooray for
> gst-v4l2!), but I remember that they often used padding areas around
> the buffer for scratch space - maybe motion vectors or similar? That
> case is quite different to something like CCS, since the data is only
> meaningful to the media engine and must be ignored (but preserved) by
> everyone else. Using multiple planes in that case isn't appropriate,
> since it's very specific to how that hardware unit deals with that
> buffer, instead of something that every consumer needs to understand
> in order to use it.

With metadata unrelated to the pixel content, using a separate plane in
the same buffer resulted in an explosion of the number of combinations
that we would need to support, and ultimately led to a very ill-defined
API. We decided to convey metadata related to the frame capture context
(e.g. what exposure time was used for the frame) and processing pipeline
configuration data in different buffers than the frame itself.

--
Regards,

Laurent Pinchart

2019-04-23 16:04:17

by Daniel Stone

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Laurent,

On Tue, 23 Apr 2019 at 16:54, Laurent Pinchart
<[email protected]> wrote:
> On Tue, Apr 23, 2019 at 09:59:37AM +0100, Daniel Stone wrote:
> > On Tue, 23 Apr 2019 at 08:26, Daniel Vetter <[email protected]> wrote:
> > Totally. Let's take DRM_FORMAT_XRGB8888 + I915_FORMAT_MOD_Y_TILED as
> > an example. [... details ...]
>
> Looks like we have different kinds of metadata to consider. On the V4L2
> side metadata usually refers to the context in which a frame was
> captured, it doesn't tell how to interpret the contents of the pixels.
> In the case you just described, the metadata is part of the frame
> contents. I agree that this is a proper use case for storing such
> metadata in a plane. What I wouldn't like to see being stored in a plane
> is for instance gamma tables or similar data that configures the
> processing pipeline in the display engine (I know we have an API for
> gamma tables, this is just an example).
>
> > It would be good to understand what you had in mind when you said that
> > using multiple planes created a mess. I haven't touched media
> > encode/decode units at a low level for quite a while (hooray for
> > gst-v4l2!), but I remember that they often used padding areas around
> > the buffer for scratch space - maybe motion vectors or similar? That
> > case is quite different to something like CCS, since the data is only
> > meaningful to the media engine and must be ignored (but preserved) by
> > everyone else. Using multiple planes in that case isn't appropriate,
> > since it's very specific to how that hardware unit deals with that
> > buffer, instead of something that every consumer needs to understand
> > in order to use it.
>
> With metadata unrelated to the pixel content, using a separate plane in
> the same buffer resulted in an explosion of the number of combinations
> that we would need to support, and ultimately led to a very ill-defined
> API. We decided to convey metadata related to the frame capture context
> (e.g. what exposure time was used for the frame) and processing pipeline
> configuration data in different buffers than the frame itself.

Yeah, that makes sense. It's not really that different from what
happens with GPUs either: the final colour buffer the display
controller gets from a game is the product of a _lot_ of other work
which is invisible to the display controller, including things like
depth and stencil buffers, command buffers, etc etc. Those are closely
related to the frame production, but totally irrelevant for exchanging
the colour buffer with other subsystems.

I think we should look at the metadata buffers you're describing in
the same way. Perhaps each V4L2 buffer could have driver-private
auxiliary buffer storage, or perhaps it's something you need to
separately expose to userspace as auxiliary data which must be
preserved but ignored. But modifiers are really only about what you
need when exchanging image colour buffers between subsystems, not
anything else.

You're pretty close with gamma tables as well; for HDR and other kinds
of complex colour management, we need to carry a fair bit of auxiliary
information in order to display the image correctly. These have quite
different uses though: normally the colour buffer is produced by the
hardware and the primaries/whitepoints/etc are produced by software,
with the colour-management details remaining static across the life of
a swapchain even as you flip between multiple buffers. Given that, it
doesn't really make sense to try to stuff them into the same storage.

Cheers,
Daniel

2019-04-23 16:40:50

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

Le mardi 23 avril 2019 à 17:02 +0100, Daniel Stone a écrit :
> Hi Laurent,
>
> On Tue, 23 Apr 2019 at 16:54, Laurent Pinchart
> <[email protected]> wrote:
> > On Tue, Apr 23, 2019 at 09:59:37AM +0100, Daniel Stone wrote:
> > > On Tue, 23 Apr 2019 at 08:26, Daniel Vetter <[email protected]> wrote:
> > > Totally. Let's take DRM_FORMAT_XRGB8888 + I915_FORMAT_MOD_Y_TILED as
> > > an example. [... details ...]
> >
> > Looks like we have different kinds of metadata to consider. On the V4L2
> > side metadata usually refers to the context in which a frame was
> > captured, it doesn't tell how to interpret the contents of the pixels.
> > In the case you just described, the metadata is part of the frame
> > contents. I agree that this is a proper use case for storing such
> > metadata in a plane. What I wouldn't like to see being stored in a plane
> > is for instance gamma tables or similar data that configures the
> > processing pipeline in the display engine (I know we have an API for
> > gamma tables, this is just an example).
> >
> > > It would be good to understand what you had in mind when you said that
> > > using multiple planes created a mess. I haven't touched media
> > > encode/decode units at a low level for quite a while (hooray for
> > > gst-v4l2!), but I remember that they often used padding areas around
> > > the buffer for scratch space - maybe motion vectors or similar? That
> > > case is quite different to something like CCS, since the data is only
> > > meaningful to the media engine and must be ignored (but preserved) by
> > > everyone else. Using multiple planes in that case isn't appropriate,
> > > since it's very specific to how that hardware unit deals with that
> > > buffer, instead of something that every consumer needs to understand
> > > in order to use it.
> >
> > With metadata unrelated to the pixel content, using a separate plane in
> > the same buffer resulted in an explosion of the number of combinations
> > that we would need to support, and ultimately led to a very ill-defined
> > API. We decided to convey metadata related to the frame capture context
> > (e.g. what exposure time was used for the frame) and processing pipeline
> > configuration data in different buffers than the frame itself.
>
> Yeah, that makes sense. It's not really that different from what
> happens with GPUs either: the final colour buffer the display
> controller gets from a game is the product of a _lot_ of other work
> which is invisible to the display controller, including things like
> depth and stencil buffers, command buffers, etc etc. Those are closely
> related to the frame production, but totally irrelevant for exchanging
> the colour buffer with other subsystems.
>
> I think we should look at the metadata buffers you're describing in
> the same way. Perhaps each V4L2 buffer could have driver-private
> auxiliary buffer storage, or perhaps it's something you need to
> separately expose to userspace as auxiliary data which must be
> preserved but ignored. But modifiers are really only about what you
> need when exchanging image colour buffers between subsystems, not
> anything else.
>
> You're pretty close with gamma tables as well; for HDR and other kinds
> of complex colour management, we need to carry a fair bit of auxiliary
> information in order to display the image correctly. These have quite
> different uses though: normally the colour buffer is produced by the
> hardware and the primaries/whitepoints/etc are produced by software,
> with the colour-management details remaining static across the life of
> a swapchain even as you flip between multiple buffers. Given that, it
> doesn't really make sense to try to stuff them into the same storage.

I agree that we need to keep things minimal and clearly distinguish
between what constitutes the description of the pixel buffer in terms
of how it's laid out in memory and information about how the data
should be interpreted.

And there's indeed a fair share of things to consider there. Adding to
the list above, I'm also thinking of the YUV colorspace information
which must be passed along when displaying a buffer.

But that's essentially not required to have a common description of
buffers unified accross subsystems. Thinking about that, it would be
interesting to have a common base structure for buffers used in v4l2
and drm. Ideally, that could be shared when doing dma-buf to avoid
having userspace describe buffers and memory each time a buffer is
imported into another subsystem. This could also help us solve the
ambiguity related to the YUV M-suffixed formats. Another idea could be
having common ioctls to get a unified buffer description from userspace
and e.g. mmap on a per-plane basis (with virtual mappings like DRM
does).

What do you think?

Cheers,

Paul

2019-04-23 16:48:02

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

Le mardi 23 avril 2019 à 18:45 +0300, Laurent Pinchart a écrit :
> Hi Daniel,
>
> On Tue, Apr 23, 2019 at 09:25:54AM +0200, Daniel Vetter wrote:
> > On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> > > On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> > > > On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> > > > > > > On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > > > > > > > On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > > > > > > > > Hi,
> > > > > > > > >
> > > > > > > > > DRM comes with an extensive format support to retrieve the various
> > > > > > > > > parameters associated with a given format (such as the subsampling, or the
> > > > > > > > > bits per pixel), as well as some helpers and utilities to ease the driver
> > > > > > > > > development.
> > > > > > > > >
> > > > > > > > > v4l2, on the other side, doesn't provide such facilities, leaving each
> > > > > > > > > driver reimplement a subset of the formats parameters for the one supported
> > > > > > > > > by that particular driver. This leads to a lot of duplication and
> > > > > > > > > boilerplate code in the v4l2 drivers.
> > > > > > > > >
> > > > > > > > > This series tries to address this by moving the DRM format API into lib and
> > > > > > > > > turning it into a more generic API. In order to do this, we've needed to do
> > > > > > > > > some preliminary changes on the DRM drivers, then moved the API and finally
> > > > > > > > > converted a v4l2 driver to give an example of how such library could be
> > > > > > > > > used.
> > > > > > > > >
> > > > > > > > > Let me know what you think,
> > > > > > > > > Maxime
> > > > > > > > >
> > > > > > > > > Changes from RFC:
> > > > > > > > > - Rebased on next
> > > > > > > > > - Fixed the various formats mapping
> > > > > > > > > - Added tags
> > > > > > > > > - Did most of the formats functions as inline functions
> > > > > > > > > - Used a consistent prefix for all the utilities functions
> > > > > > > > > - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > > > > > > > > arm64 and x86_64
> > > > > > > > > - Fixed out of array bounds warnings in the image_format_info_block_*
> > > > > > > > > functions
> > > > > > > > > - Added License and copyright headers on missing files
> > > > > > > > >
> > > > > > > > > Maxime Ripard (20):
> > > > > > > > > drm: Remove users of drm_format_num_planes
> > > > > > > > > drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > > > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > > > > > > > > drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > > > > > > > > drm: Replace instances of drm_format_info by drm_get_format_info
> > > > > > > > > lib: Add video format information library
> > > > > > > > > drm/fb: Move from drm_format_info to image_format_info
> > > > > > > > > drm/malidp: Convert to generic image format library
> > > > > > > > > drm/client: Convert to generic image format library
> > > > > > > > > drm/exynos: Convert to generic image format library
> > > > > > > > > drm/i915: Convert to generic image format library
> > > > > > > > > drm/ipuv3: Convert to generic image format library
> > > > > > > > > drm/msm: Convert to generic image format library
> > > > > > > > > drm/omap: Convert to generic image format library
> > > > > > > > > drm/rockchip: Convert to generic image format library
> > > > > > > > > drm/tegra: Convert to generic image format library
> > > > > > > > > drm/fourcc: Remove old DRM format API
> > > > > > > > > lib: image-formats: Add v4l2 formats support
> > > > > > > > > lib: image-formats: Add more functions
> > > > > > > > > media: sun6i: Convert to the image format API
> > > > > > > >
> > > > > > > > In the interest of making myself unpopular: Why move this out of drm?
> > > > > > > >
> > > > > > > > We do have a bunch of other such shared helpers already (mostly in
> > > > > > > > drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > > > > > > > sure that's going better than keeping it maintained in drm.
> > >
> > > That's a bit of a different situation as both DRM and FBDEV address the
> > > same features (display output), and FBDEV is deprecared and replaced by
> > > DRM.
> > >
> > > I'm not against maintaining a 4CC library in DRM (adding a third-party
> > > maintainer would likely create more problems than it would solve), but
> > > that doesn't mean the library has to live in drivers/gpu/, nor that it
> > > needs to have the drm_ prefix. I would actually advocate to make it live
> > > in a neutral directory, with a neutral prefix (kudos to anyone who can
> > > propose a nice naming convention that would establish a new shared
> > > ground for image/video-related Linux APIs), and maintained through the
> > > DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> > > reaches all the related folks).
> > >
> > > > > > > > Plus the uapi is already that you include drm_fourcc.h to get at these,
> > > > > > > > dropping the drm prefix isn't going to help I think.
> > > > > > > >
> > > > > > > > Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > > > > > > > use it without dragging in all of drm), and we need to add some fields for
> > > > > > > > converting to v4l fourcc codes (which are different). But that should be
> > > > > > > > all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > > > > > > > it's actually a feature: It makes it really clear that these are the drm
> > > > > > > > fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > > > > > > > that. That allocation authority is also already baked into various khr/ext
> > > > > > > > standards, too.
> > >
> > > There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> > > documentation. Look at
> > > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> > > or
> > > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> > > for instance. It's painful to write, painful to read, but defines the
> > > 4CCs very clearly without ambiguity. I wouldn't be surprised if
> > > different drivers used the same DRM 4CC for different formats due to the
> > > lack of detailed documentation. Moving to a shared library for 4CCs
> > > should also address the documentation side, and any new format added to
> > > the kernel, whether from the V4L2 side or the DRM side, would be
> > > required to provide detailed documentation. That would be a great
> > > improvement for DRM 4CC handling.
> > >
> > > > > > > The way I see it, there's a fundamental difference between the UAPI
> > > > > > > and the kernel. I don't suggest we change anything about the UAPI: the
> > > > > > > drm formats should keep their prefix, drm_fourcc.h can remain that
> > > > > > > authority, it's all fine.
> > > > > > >
> > > > > > > Internally however, the long term goal is to share the fourcc's
> > > > > > > between DRM and V4L2 for the same formats. It basically means that of
> > > > > > > course v4l2 should be using the DRM fourcc when a format exists in DRM
> > > > > > > and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > > > > > > exists in v4l2 but not DRM, and that is far more likely, given the
> > > > > > > already extensive v4l2 formats support.
> > > > > >
> > > > > > Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > > > > > format identifier space.
> > > > >
> > > > > No to what exactly?
> > > > >
> > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > really it's totally not.
> > > > >
> > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > >
> > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > for the fourcc, so it definitely looks like a standard to me.
> > > >
> > > > drm fourcc is the authority for drm fourcc codes. Not for any of the
> > > > others (and there's lots of them). Now it's used in a bunch of other
> > > > places (khr standards, dri protocols in wayland/X11), but they're
> > > > still only drm fourcc. There is no overall fourcc standard.
> > > >
> > > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > > in modifiers a lot more.
> > > > >
> > > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > > >
> > > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > > valid as ever:
> > > > > >
> > > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > > >
> > > > > Do yo have an example of one of those areas?
> > > >
> > > > I think the rgb stuff was one of the big reasons to not reuse any
> > > > existing fourcc standard (whether v4l, or another one from e.g. video
> > > > container formats). We had initial patches to reuse the fourcc that
> > > > existed, but the end result was really inconsistent, so we ditch that
> > > > and rolled out a new set of entirely drm specific fourcc codes for
> > > > rgba.
> > >
> > > Could you give one or a couple of examples of V4L2 4CCs that are not
> > > OCD-compatible ? :-)
> > >
> > > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > > e.g. offset for planar yuv formats, or tiling mode
> > > > >
> > > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > > what DRM is doing.
> > > > >
> > > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > > uniquely, drivers can override that (that's an explicit design
> > > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > > e.g. compression information). You'd need to pull that driver
> > > > > > knowledge into your format library.
> > >
> > > That's a mistake in my opinion. We tried that in V4L2 to store metadata
> > > in a separate plane, and had to go another route eventually as it
> > > created a very bad mess.
> >
> > Just quick clarification in the middle here: This is how the hw works.
>
> The hardware takes parameters from a buffer, but it doesn't mandate how
> that buffer is exposed to userspace :-) Using an extra plane is one
> option, but other APIs are possible.
>
> > It's not metadata that sw ever touches (in general, testcases to make sure
> > we display these correctly excepted).
> >
> > There has been some talking to add maybe a bit more mixed metadata, for
> > fast-clear colors (which isn't used by any display engine afaik yet). That
>
> What are fast-clear colors ?
>
> > would generally be written by the cpu (in the gl stack), but again read by
> > the hw (loaded as indirect state packet most likely, or something like
> > that). So again hw specific layout, because the hw needs to read it.
> >
> > Pure metadata only of interest for the cpu/sw stack has been shot down
> > completely on the drm side too.
> >
> > > There's a tendency in both subsystems to look at the other as a bit of a
> > > retarded relative, and that's a shame, we have lots to learn from each
> > > other's mistakes. That wouldn't be too difficult if people started
> > > talking to each other.
> > >
> > > A semi-related comment: DRM also carries other mistakes of its own, I'm
> > > thinking about DRM_FORMAT_BIG_ENDIAN in particular
> >
> > Yeah that one is hilarios, but in practice big endian is dead, except for
> > a very few server chips, and there I think Gerd's work mostly fixed up
> > that mess.
> >
> > > > > I'm not sure how my patches are changing anything here. This is
> > > > > litterally the same code, with the functions renamed.
> > > > >
> > > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > > that. Just like any helper this just provides a default that covers
> > > > > most of the cases.
> > > > >
> > > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > > something like a new addfb flag.
> > > > >
> > > > > For the formats that would be described as a modifier, sure. For all
> > > > > the others (that are not yet supported by DRM), then I don't really
> > > > > see why not.
> > > >
> > > > See above, we tried that initially, didn't pass the ocd tests when
> > > > reviewing. Maybe the situation is better outside of rbgx/a formats,
> > > > and I think we do at least try to use the same fourcc codes there when
> > > > there already is one. But then the details occasionally look
> > > > different.
> > > >
> > > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > > >
> > > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > > since it will be easy to discover the formats that are already
> > > > > > > supported by the other subsystem.
> > > > > >
> > > > > > I think a compat library that (tries to, best effort) convert between
> > > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > > perhaps. That should be useful for drivers.
> > > > >
> > > > > That's not really what this series is about though. That series is
> > > > > about sharing the (image|pixels) formats database across everyone so
> > > > > that everyone can benefit from it.
> > > >
> > > > Yeah I know. I still think leaving the drm fourcc with the drm prefix
> > > > would be good, since there's really no standard here.
> > > >
> > > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > > drm_fourcc a few years back.
> > > > > >
> > > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > > then:
> > > > > > >
> > > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > > would work.
> > > > > >
> > > > > > Well, if we end up with a common library then yes we need cross
> > > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > > they get cross-posted is easy. No file renaming needed.
> > > > >
> > > > > That would create some governing issues as well. For example, if you
> > > > > ever have a patch from one fourcc addition (that might or might not be
> > > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > >
> > > > None of this is fixed by code renaming or locations. Either way we
> > > > need to figure that out.
> > > >
> > > > And yes part of the reasons for not moving this out of drm is that I'm
> > > > not a fan of boutique trees for small stuff. If sharing means we need
> > > > to split the drm_fourcc code and library out of drm trees, I'm not
> > > > sure that's a good idea. We're already super liberal with merging
> > > > anything through driver trees with acks, and integrating them quickly
> > > > into drm-next. This would still be workable if v4l sends regular pull
> > > > requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > > > do). If we can only sync up once per merge window with a shared
> > > > boutique tree for formats only, life is going to be painful.
> > >
> > > That should be solved by the proposal above, maintaining the shared
> > > library in the DRM tree. We would need to be careful there, and ideally
> > > maintain that in a separate branch that could be merged in both DRM and
> > > V4L2 without having to merge most of the other subsystem's pending
> > > changes at the same time, but I think it's doable without any big issue.
> > >
> > > > > If it's shared code, then it should be shared, and every client
> > > > > framework put on an equal footing.
> > > > >
> > > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > > solution, since the information would be greatly duplicated
> > > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > > size that would be duplicated too.
> > > > > >
> > > > > > It's essentially what we decided to do for drm years back.
> > > > >
> > > > > And it was probably the right solution back then, but I'm really not
> > > > > convinced it's still the right thing to do today.
> > > > >
> > > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > > centralized.
> > > > > >
> > > > > > What I think could work as middle ground:
> > > > > > - Put drm_format stuff into a separate .ko
> > > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > > and v4l formats. On the drm side that most likely means you need
> > > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > > the drivers that use this library need.
> > > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > > format space.
> > > > > >
> > > > > > Forcing this unification on everyone otoh is imo way too much.
> > > > >
> > > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > > pretty much untouched for that library, so I'm not really sure how
> > > > > anyone is hurt by that unification.
> > > >
> > > > It might make sense to regularly pull v4l updates into drm-next then
> > > > anyway. That would also remove the need to have the format library
> > > > somewhere else.
> > >
> > > Are you saying it should the live in V4L2 ? ;-)
> >
> > Maybe a few clarifications on how the drm shared core thing usually works,
> > and why I'm a sticker here. Bottom reply since I'm not sure where to put
> > it:
> >
> > - Refactorings usually go in through drm-misc (at least since a few
> > years).
> >
> > - Small patches go in through the relevant driver tree (which is often
> > drm-misc, but not always), with an Ack from drm maintainers.
> >
> > - No topic branches, everyone just pushes patches where it's most
> > convenient.
> >
> > We get away with this mess because everyone sends regular pull requests to
> > drm, where the entire history is baked in and others can backmerge/fast
> > forward/rebase. Worst case you wait one month (around the merge window,
> > when drm-next is closed for features), but usually it's just 1-2 weeks.
> > Plus we tend to have fairly big trees, with good chances that the next
> > patch series lands in the same tree again and no work at all is needed.
> >
> > If we start regularly sharing lots of code with v4l (which seems to be the
> > long term goal here), then I think we need something equally convenient
> > for all that.
> >
> > We're not going to be able to teach some complicated topic branch scheme
> > to the 50+ submaintainers/committers we have in drm - a lot much more
> > basic stuff already takes lots of work to get it to stick. If the proposal
> > is "to be careful" and "maintain it in a separate branch", I'm not in
> > favour because I think that just wouldn't work.
>
> Why not ? It can be a fast-moving branch that gets merged in drm-misc
> as often as you want (even at every commit if that's desired). We're
> dealing with a limited amount of code here, and there's no more reason
> that V4L2 should pull in drm-misc to get 4CC updates than DRM should
> pull V4L2 for the same. I have no objection against a 4CC branch being
> officially maintained under the DRM umbrella, but I think the code
> should live elsewhere than drivers/gpu/drm/, have a neutral prefix, and
> not require pulling an entire subsystem in.

I think that having a subsystem-neutral tree is what Maxime had in mind
initially. The way I see it, the idea would indeed be to keep it low-
traffic and avoid having any serious core code in there. Basically just
stick to format helpers and ideally later buffer description structures
and helpers.

I also like the idea of having a few shared ioctls to retrieve a buffer
memory layout information from a dma-buf fd and mmap-ing on a per-plane
basis, but that's rather unlikely to evolve much once it's there.

Cheers,

Paul

2019-04-23 16:56:27

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi,

Le dimanche 21 avril 2019 à 01:40 +0300, Laurent Pinchart a écrit :
> Hi Paul,
>
> On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > really it's totally not.
> > >
> > > Even if it's not a standard, having consistency would be a good thing.
> > >
> > > And you said yourself that DRM fourcc is now pretty much an authority
> > > for the fourcc, so it definitely looks like a standard to me.
> >
> > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > cause, as it has already significantly diverged. Even if we coordinate
> > an effort to introduce new formats with the same fourcc on both sides,
> > I don't see what good that would be since the formats we have now are
> > still plagued by the inconsistency.
> >
> > I think we always need an explicit translation step from either v4l2 or
> > drm to the internal representation and back, without ever assuming that
> > formats might be compatible because they share the same fourcc.
>
> I don't agree. APIs evolve, and while we can't switch from one set of
> 4CCs to another in existing APIs, we could in new APIs. Boris is working
> on new ioctls to handle formats in V4L2, and while 4CC unification could
> be impopular from a userspace developers point of view there, I don't
> think we have ruled it out completely. The move to the request API is
> also an area where a common set of 4CCs could be used, as it will depart
> from the existing V4L2 ioctls. To summarize my opinion, we're not there
> yet, but I wouldn't rule it out completely for the future.

Well, I don't see how we could maintain backward compatibility with
some DRM and V4L2 fourccs that are compatible and some that aren't.
Since both descriptions have diverged already, one would need explicit
checking of whether the format at hand is a compatible one or not
before passing-it along as-is to the other subsystem or going through a
format conversion step (in userspace, duplicating the information).
So it feels like it kind of defeats the purpose.

If we're going to use a unified 4CC representation in the future, I
think we should do it by using the new formats that this proposal is
introducing instead of subsystem-specific formats. At which point I
believe we will need an internal conversion step between that format
and what the subsystem uses internally. Or do it the other way round
and use the unified format all around the subsystem, with a legacy
layer for the previous subsystem-specific format.

Cheers,

Paul

2019-04-23 16:57:45

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 06/20] lib: Add video format information library

Hi,

Le mardi 23 avril 2019 à 13:22 +0200, Thomas Zimmermann a écrit :
> Hi
>
> Am 17.04.19 um 09:54 schrieb Maxime Ripard:
> > Move the DRM formats API to turn this into a more generic image formats API
> > to be able to leverage it into some other places of the kernel, such as
> > v4l2 drivers.
>
> Here's some nitpicking: 'image_format_*' appears slightly vague; it
> could refer to a disk or ROM image as well. Something like
> 'pixel_format_*', 'pixbuf_format_*', etc. would clearly indicate graphics.

Yeah I'm with you on this one. It's bike-shedding, but I think it's
fine as long as more fundamental topics are moving as well.

Cheers,

Paul

> Best regards
> Thomas
>
> > Signed-off-by: Maxime Ripard <[email protected]>
> > ---
> > include/linux/image-formats.h | 387 +++++++++++++++++++++-
> > lib/Kconfig | 7 +-
> > lib/Makefile | 3 +-
> > lib/image-formats-selftests.c | 325 +++++++++++++++++-
> > lib/image-formats.c | 655 +++++++++++++++++++++++++++++++++++-
> > 5 files changed, 1377 insertions(+)
> > create mode 100644 include/linux/image-formats.h
> > create mode 100644 lib/image-formats-selftests.c
> > create mode 100644 lib/image-formats.c
> >
> > diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> > new file mode 100644
> > index 000000000000..ec43d9f9a527
> > --- /dev/null
> > +++ b/include/linux/image-formats.h
> > @@ -0,0 +1,387 @@
> > +/*
> > + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> > + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> > + *
> > + * 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.
> > + */
> > +
> > +#ifndef _IMAGE_FORMATS_H_
> > +#define _IMAGE_FORMATS_H_
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/types.h>
> > +
> > +/**
> > + * struct image_format_info - information about a image format
> > + */
> > +struct image_format_info {
> > + union {
> > + /**
> > + * @drm_fmt:
> > + *
> > + * DRM 4CC format identifier (DRM_FORMAT_*)
> > + */
> > + u32 drm_fmt;
> > +
> > + /**
> > + * @format:
> > + *
> > + * DRM 4CC format identifier (DRM_FORMAT_*). Kept
> > + * around for compatibility reasons with the current
> > + * DRM drivers.
> > + */
> > + u32 format;
> > + };
> > +
> > + /**
> > + * @depth:
> > + *
> > + * Color depth (number of bits per pixel excluding padding bits),
> > + * valid for a subset of RGB formats only. This is a legacy field, do
> > + * not use in new code and set to 0 for new formats.
> > + */
> > + u8 depth;
> > +
> > + /** @num_planes: Number of color planes (1 to 3) */
> > + u8 num_planes;
> > +
> > + union {
> > + /**
> > + * @cpp:
> > + *
> > + * Number of bytes per pixel (per plane), this is aliased with
> > + * @char_per_block. It is deprecated in favour of using the
> > + * triplet @char_per_block, @block_w, @block_h for better
> > + * describing the pixel format.
> > + */
> > + u8 cpp[3];
> > +
> > + /**
> > + * @char_per_block:
> > + *
> > + * Number of bytes per block (per plane), where blocks are
> > + * defined as a rectangle of pixels which are stored next to
> > + * each other in a byte aligned memory region. Together with
> > + * @block_w and @block_h this is used to properly describe tiles
> > + * in tiled formats or to describe groups of pixels in packed
> > + * formats for which the memory needed for a single pixel is not
> > + * byte aligned.
> > + *
> > + * @cpp has been kept for historical reasons because there are
> > + * a lot of places in drivers where it's used. In drm core for
> > + * generic code paths the preferred way is to use
> > + * @char_per_block, image_format_info_block_width() and
> > + * image_format_info_block_height() which allows handling both
> > + * block and non-block formats in the same way.
> > + *
> > + * For formats that are intended to be used only with non-linear
> > + * modifiers both @cpp and @char_per_block must be 0 in the
> > + * generic format table. Drivers could supply accurate
> > + * information from their drm_mode_config.get_format_info hook
> > + * if they want the core to be validating the pitch.
> > + */
> > + u8 char_per_block[3];
> > + };
> > +
> > + /**
> > + * @block_w:
> > + *
> > + * Block width in pixels, this is intended to be accessed through
> > + * image_format_info_block_width()
> > + */
> > + u8 block_w[3];
> > +
> > + /**
> > + * @block_h:
> > + *
> > + * Block height in pixels, this is intended to be accessed through
> > + * image_format_info_block_height()
> > + */
> > + u8 block_h[3];
> > +
> > + /** @hsub: Horizontal chroma subsampling factor */
> > + u8 hsub;
> > + /** @vsub: Vertical chroma subsampling factor */
> > + u8 vsub;
> > +
> > + /** @has_alpha: Does the format embeds an alpha component? */
> > + bool has_alpha;
> > +
> > + /** @is_yuv: Is it a YUV format? */
> > + bool is_yuv;
> > +};
> > +
> > +/**
> > + * image_format_info_is_yuv_packed - check that the format info matches a YUV
> > + * format with data laid in a single plane
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a packed YUV format.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_packed(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->num_planes == 1;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_semiplanar - check that the format info matches a YUV
> > + * format with data laid in two planes (luminance and chrominance)
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a semiplanar YUV format.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_semiplanar(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->num_planes == 2;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_planar - check that the format info matches a YUV
> > + * format with data laid in three planes (one for each YUV component)
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a planar YUV format.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_planar(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->num_planes == 3;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_sampling_410 - check that the format info matches a
> > + * YUV format with 4:1:0 sub-sampling
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a YUV format with 4:1:0
> > + * sub-sampling.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_sampling_410(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->hsub == 4 && info->vsub == 4;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_sampling_411 - check that the format info matches a
> > + * YUV format with 4:1:1 sub-sampling
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a YUV format with 4:1:1
> > + * sub-sampling.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_sampling_411(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->hsub == 4 && info->vsub == 1;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_sampling_420 - check that the format info matches a
> > + * YUV format with 4:2:0 sub-sampling
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a YUV format with 4:2:0
> > + * sub-sampling.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_sampling_420(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->hsub == 2 && info->vsub == 2;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_sampling_422 - check that the format info matches a
> > + * YUV format with 4:2:2 sub-sampling
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a YUV format with 4:2:2
> > + * sub-sampling.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_sampling_422(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->hsub == 2 && info->vsub == 1;
> > +}
> > +
> > +/**
> > + * image_format_info_is_yuv_sampling_444 - check that the format info matches a
> > + * YUV format with 4:4:4 sub-sampling
> > + * @info: format info
> > + *
> > + * Returns:
> > + * A boolean indicating whether the format info matches a YUV format with 4:4:4
> > + * sub-sampling.
> > + */
> > +static inline bool
> > +image_format_info_is_yuv_sampling_444(const struct image_format_info *info)
> > +{
> > + return info->is_yuv && info->hsub == 1 && info->vsub == 1;
> > +}
> > +
> > +/**
> > + * image_format_info_plane_cpp - determine the bytes per pixel value
> > + * @format: pixel format info
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The bytes per pixel value for the specified plane.
> > + */
> > +static inline
> > +int image_format_info_plane_cpp(const struct image_format_info *info, int plane)
> > +{
> > + if (!info || plane >= info->num_planes)
> > + return 0;
> > +
> > + return info->cpp[plane];
> > +}
> > +
> > +/**
> > + * image_format_info_plane_width - width of the plane given the first plane
> > + * @format: pixel format info
> > + * @width: width of the first plane
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The width of @plane, given that the width of the first plane is @width.
> > + */
> > +static inline
> > +int image_format_info_plane_width(const struct image_format_info *info, int width,
> > + int plane)
> > +{
> > + if (!info || plane >= info->num_planes)
> > + return 0;
> > +
> > + if (plane == 0)
> > + return width;
> > +
> > + return width / info->hsub;
> > +}
> > +
> > +/**
> > + * image_format_info_plane_height - height of the plane given the first plane
> > + * @format: pixel format info
> > + * @height: height of the first plane
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The height of @plane, given that the height of the first plane is @height.
> > + */
> > +static inline
> > +int image_format_info_plane_height(const struct image_format_info *info, int height,
> > + int plane)
> > +{
> > + if (!info || plane >= info->num_planes)
> > + return 0;
> > +
> > + if (plane == 0)
> > + return height;
> > +
> > + return height / info->vsub;
> > +}
> > +
> > +/**
> > + * image_format_info_block_width - width in pixels of block.
> > + * @format: pointer to the image_format_info
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The width in pixels of a block, depending on the plane index.
> > + */
> > +static inline
> > +unsigned int image_format_info_block_width(const struct image_format_info *format,
> > + int plane)
> > +{
> > + if (!format)
> > + return 0;
> > +
> > + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> > + return 0;
> > +
> > + if (plane >= format->num_planes)
> > + return 0;
> > +
> > + if (!format->block_w[plane])
> > + return 1;
> > +
> > + return format->block_w[plane];
> > +}
> > +
> > +/**
> > + * image_format_info_block_height - height in pixels of a block
> > + * @info: pointer to the image_format_info
> > + * @plane: plane index
> > + *
> > + * Returns:
> > + * The height in pixels of a block, depending on the plane index.
> > + */
> > +static inline
> > +unsigned int image_format_info_block_height(const struct image_format_info *format,
> > + int plane)
> > +{
> > + if (!format)
> > + return 0;
> > +
> > + if (plane < 0 || plane >= ARRAY_SIZE(format->block_w))
> > + return 0;
> > +
> > + if (plane >= format->num_planes)
> > + return 0;
> > +
> > + if (!format->block_h[plane])
> > + return 1;
> > +
> > + return format->block_h[plane];
> > +}
> > +
> > +/**
> > + * image_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.
> > + */
> > +static inline
> > +uint64_t image_format_info_min_pitch(const struct image_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],
> > + image_format_info_block_width(info, plane) *
> > + image_format_info_block_height(info, plane));
> > +}
> > +
> > +const struct image_format_info *__image_format_drm_lookup(u32 drm);
> > +const struct image_format_info *image_format_drm_lookup(u32 drm);
> > +
> > +#endif /* _IMAGE_FORMATS_H_ */
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index fb453afff32e..9a0160d3123b 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -625,3 +625,10 @@ config GENERIC_LIB_UCMPDI2
> >
> > config OBJAGG
> > tristate "objagg" if COMPILE_TEST
> > +
> > +config IMAGE_FORMATS
> > + bool
> > +
> > +config IMAGE_FORMATS_SELFTESTS
> > + tristate "Test image format functions"
> > + depends on IMAGE_FORMATS
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 6996d2b9f401..203336b91248 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -280,3 +280,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
> > obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
> > obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
> > obj-$(CONFIG_OBJAGG) += objagg.o
> > +
> > +obj-$(CONFIG_IMAGE_FORMATS) += image-formats.o
> > +obj-$(CONFIG_IMAGE_FORMATS_SELFTESTS) += image-formats-selftests.o
> > diff --git a/lib/image-formats-selftests.c b/lib/image-formats-selftests.c
> > new file mode 100644
> > index 000000000000..d0f0011b535e
> > --- /dev/null
> > +++ b/lib/image-formats-selftests.c
> > @@ -0,0 +1,325 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Test cases for the image_format functions
> > + */
> > +
> > +#define pr_fmt(fmt) "image_format: " fmt
> > +
> > +#include <linux/errno.h>
> > +#include <linux/image-formats.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +
> > +#include <drm/drm_fourcc.h>
> > +
> > +#define FAIL(test, msg, ...) \
> > + do { \
> > + if (test) { \
> > + pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
> > + return -EINVAL; \
> > + } \
> > + } while (0)
> > +
> > +#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
> > +
> > +static int test_image_format_info_block_width(void)
> > +{
> > + const struct image_format_info *info = NULL;
> > +
> > + /* Test invalid arguments */
> > + FAIL_ON(image_format_info_block_width(info, 0) != 0);
> > + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> > + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> > +
> > + /* Test 1 plane format */
> > + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> > + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> > +
> > + /* Test 2 planes format */
> > + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 2) != 0);
> > + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> > +
> > + /* Test 3 planes format */
> > + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_width(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 1) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 2) != 1);
> > + FAIL_ON(image_format_info_block_width(info, 3) != 0);
> > + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> > +
> > + /* Test a tiled format */
> > + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_width(info, 0) != 2);
> > + FAIL_ON(image_format_info_block_width(info, 1) != 0);
> > + FAIL_ON(image_format_info_block_width(info, -1) != 0);
> > +
> > + return 0;
> > +}
> > +
> > +static int test_image_format_info_block_height(void)
> > +{
> > + const struct image_format_info *info = NULL;
> > +
> > + /* Test invalid arguments */
> > + FAIL_ON(image_format_info_block_height(info, 0) != 0);
> > + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> > + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> > +
> > + /* Test 1 plane format */
> > + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> > + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> > +
> > + /* Test 2 planes format */
> > + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 2) != 0);
> > + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> > +
> > + /* Test 3 planes format */
> > + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_height(info, 0) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 1) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 2) != 1);
> > + FAIL_ON(image_format_info_block_height(info, 3) != 0);
> > + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> > +
> > + /* Test a tiled format */
> > + info = image_format_drm_lookup(DRM_FORMAT_X0L0);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_block_height(info, 0) != 2);
> > + FAIL_ON(image_format_info_block_height(info, 1) != 0);
> > + FAIL_ON(image_format_info_block_height(info, -1) != 0);
> > +
> > + return 0;
> > +}
> > +
> > +static int test_image_format_info_min_pitch(void)
> > +{
> > + const struct image_format_info *info = NULL;
> > +
> > + /* Test invalid arguments */
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + /* Test 1 plane 8 bits per pixel format */
> > + info = image_format_drm_lookup(DRM_FORMAT_RGB332);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> > + (uint64_t)(UINT_MAX - 1));
> > +
> > + /* Test 1 plane 16 bits per pixel format */
> > + info = image_format_drm_lookup(DRM_FORMAT_XRGB4444);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX * 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> > + (uint64_t)(UINT_MAX - 1) * 2);
> > +
> > + /* Test 1 plane 24 bits per pixel format */
> > + info = image_format_drm_lookup(DRM_FORMAT_RGB888);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 3);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 6);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1920);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 3072);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 5760);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 12288);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2013);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX * 3);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> > + (uint64_t)(UINT_MAX - 1) * 3);
> > +
> > + /* Test 1 plane 32 bits per pixel format */
> > + info = image_format_drm_lookup(DRM_FORMAT_ABGR8888);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 4);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 8);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 2560);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 4096);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 7680);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 16384);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 2684);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX * 4);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> > + (uint64_t)(UINT_MAX - 1) * 4);
> > +
> > + /* Test 2 planes format */
> > + info = image_format_drm_lookup(DRM_FORMAT_NV12);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 640);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 1024);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 1920);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 4096);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 672);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> > + (uint64_t)UINT_MAX + 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
> > + (uint64_t)(UINT_MAX - 1));
> > + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> > + (uint64_t)(UINT_MAX - 1));
> > +
> > + /* Test 3 planes 8 bits per pixel format */
> > + info = image_format_drm_lookup(DRM_FORMAT_YUV422);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 3, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 1) != 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 1) != 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 2) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 2) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 640);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 320) != 320);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 320) != 320);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 1024);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 512) != 512);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 512) != 512);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 1920);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 960) != 960);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 960) != 960);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 4096);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 2048) != 2048);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 2048) != 2048);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 671);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 336) != 336);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, 336) != 336);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
> > + (uint64_t)UINT_MAX / 2 + 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
> > + (uint64_t)UINT_MAX / 2 + 1);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
> > + (uint64_t)(UINT_MAX - 1) / 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
> > + (uint64_t)(UINT_MAX - 1) / 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
> > + (uint64_t)(UINT_MAX - 1) / 2);
> > +
> > + /* Test tiled format */
> > + info = image_format_drm_lookup(DRM_FORMAT_X0L2);
> > + FAIL_ON(!info);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, -1, 0) != 0);
> > + FAIL_ON(image_format_info_min_pitch(info, 1, 0) != 0);
> > +
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1) != 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 2) != 4);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 640) != 1280);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1024) != 2048);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 1920) != 3840);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 4096) != 8192);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, 671) != 1342);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX) !=
> > + (uint64_t)UINT_MAX * 2);
> > + FAIL_ON(image_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
> > + (uint64_t)(UINT_MAX - 1) * 2);
> > +
> > + return 0;
> > +}
> > +
> > +#define selftest(test) { .name = #test, .func = test, }
> > +
> > +static struct image_format_test {
> > + char *name;
> > + int (*func)(void);
> > +} tests[] = {
> > + selftest(test_image_format_info_block_height),
> > + selftest(test_image_format_info_block_width),
> > + selftest(test_image_format_info_min_pitch),
> > +};
> > +
> > +static int __init image_format_test_init(void)
> > +{
> > + unsigned int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(tests); i++) {
> > + struct image_format_test *test = &tests[i];
> > + int ret;
> > +
> > + ret = test->func();
> > + if (ret) {
> > + pr_err("Failed test %s\n", test->name);
> > + return ret;
> > + }
> > + }
> > +
> > + pr_info("All tests executed properly.\n");
> > + return 0;
> > +}
> > +module_init(image_format_test_init);
> > +
> > +MODULE_AUTHOR("Intel Corporation");
> > +MODULE_AUTHOR("Maxime Ripard <[email protected]>");
> > +MODULE_LICENSE("GPL");
> > diff --git a/lib/image-formats.c b/lib/image-formats.c
> > new file mode 100644
> > index 000000000000..1e52a7410222
> > --- /dev/null
> > +++ b/lib/image-formats.c
> > @@ -0,0 +1,655 @@
> > +/*
> > + * Copyright (c) 2016 Laurent Pinchart <[email protected]>
> > + * Copyright (c) 2019 Maxime Ripard <[email protected]>
> > + *
> > + * 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/image-formats.h>
> > +#include <linux/kernel.h>
> > +#include <linux/math64.h>
> > +
> > +#include <uapi/drm/drm_fourcc.h>
> > +
> > +static const struct image_format_info formats[] = {
> > + {
> > + .drm_fmt = DRM_FORMAT_C8,
> > + .depth = 8,
> > + .num_planes = 1,
> > + .cpp = { 1, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGB332,
> > + .depth = 8,
> > + .num_planes = 1,
> > + .cpp = { 1, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGR233,
> > + .depth = 8,
> > + .num_planes = 1,
> > + .cpp = { 1, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XRGB4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XBGR4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBX4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRX4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ARGB4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ABGR4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBA4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRA4444,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XRGB1555,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XBGR1555,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBX5551,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRX5551,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ARGB1555,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ABGR1555,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBA5551,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRA5551,
> > + .depth = 15,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGB565,
> > + .depth = 16,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGR565,
> > + .depth = 16,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGB888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 3, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGR888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 3, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XRGB8888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XBGR8888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBX8888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRX8888,
> > + .depth = 24,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGB565_A8,
> > + .depth = 24,
> > + .num_planes = 2,
> > + .cpp = { 2, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGR565_A8,
> > + .depth = 24,
> > + .num_planes = 2,
> > + .cpp = { 2, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XRGB2101010,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XBGR2101010,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBX1010102,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRX1010102,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ARGB2101010,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ABGR2101010,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBA1010102,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRA1010102,
> > + .depth = 30,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ARGB8888,
> > + .depth = 32,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_ABGR8888,
> > + .depth = 32,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBA8888,
> > + .depth = 32,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRA8888,
> > + .depth = 32,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGB888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 3, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGR888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 3, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XRGB8888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 4, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XBGR8888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 4, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_RGBX8888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 4, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_BGRX8888_A8,
> > + .depth = 32,
> > + .num_planes = 2,
> > + .cpp = { 4, 1, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUV410,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 4,
> > + .vsub = 4,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVU410,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 4,
> > + .vsub = 4,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUV411,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 4,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVU411,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 4,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUV420,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 2,
> > + .vsub = 2,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVU420,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 2,
> > + .vsub = 2,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUV422,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVU422,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUV444,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVU444,
> > + .depth = 0,
> > + .num_planes = 3,
> > + .cpp = { 1, 1, 1 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV12,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 2,
> > + .vsub = 2,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV21,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 2,
> > + .vsub = 2,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV16,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV61,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV24,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_NV42,
> > + .depth = 0,
> > + .num_planes = 2,
> > + .cpp = { 1, 2, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YUYV,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_YVYU,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_UYVY,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_VYUY,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 2, 0, 0 },
> > + .hsub = 2,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_XYUV8888,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = DRM_FORMAT_AYUV,
> > + .depth = 0,
> > + .num_planes = 1,
> > + .cpp = { 4, 0, 0 },
> > + .hsub = 1,
> > + .vsub = 1,
> > + .has_alpha = true,
> > + .is_yuv = true,
> > + }, {
> > + .drm_fmt = 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,
> > + }, {
> > + .drm_fmt = 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,
> > + }, {
> > + .drm_fmt = 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,
> > + }, {
> > + .drm_fmt = 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,
> > + },
> > +};
> > +
> > +#define __image_format_lookup(_field, _fmt) \
> > + ({ \
> > + const struct image_format_info *format = NULL; \
> > + unsigned i; \
> > + \
> > + for (i = 0; i < ARRAY_SIZE(formats); i++) \
> > + if (formats[i]._field == _fmt) \
> > + format = &formats[i]; \
> > + \
> > + format; \
> > + })
> > +
> > +/**
> > + * __image_format_drm_lookup - query information for a given format
> > + * @drm: DRM fourcc pixel format (DRM_FORMAT_*)
> > + *
> > + * The caller should only pass a supported pixel format to this function.
> > + *
> > + * Returns:
> > + * The instance of struct image_format_info that describes the pixel format, or
> > + * NULL if the format is unsupported.
> > + */
> > +const struct image_format_info *__image_format_drm_lookup(u32 drm)
> > +{
> > + return __image_format_lookup(drm_fmt, drm);
> > +}
> > +EXPORT_SYMBOL(__image_format_drm_lookup);
> > +
> > +/**
> > + * image_format_drm_lookup - query information for a given format
> > + * @drm: DRM fourcc 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 image_format_info that describes the pixel format, or
> > + * NULL if the format is unsupported.
> > + */
> > +const struct image_format_info *image_format_drm_lookup(u32 drm)
> > +{
> > + const struct image_format_info *format;
> > +
> > + format = __image_format_drm_lookup(drm);
> > +
> > + WARN_ON(!format);
> > + return format;
> > +}
> > +EXPORT_SYMBOL(image_format_drm_lookup);
> >

2019-04-23 17:19:45

by Nicolas Dufresne

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Le mardi 23 avril 2019 à 17:09 +0200, Daniel Vetter a écrit :
> On Tue, Apr 23, 2019 at 4:28 PM Nicolas Dufresne <[email protected]> wrote:
> > Le mardi 23 avril 2019 à 14:33 +0200, Paul Kocialkowski a écrit :
> > > Hi,
> > >
> > > On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> > > > On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > > > > Hi Paul,
> > > > >
> > > > > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > > > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > > > really it's totally not.
> > > > > > >
> > > > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > > > >
> > > > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > > > for the fourcc, so it definitely looks like a standard to me.
> > > > > >
> > > > > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > > > > cause, as it has already significantly diverged. Even if we coordinate
> > > > > > an effort to introduce new formats with the same fourcc on both sides,
> > > > > > I don't see what good that would be since the formats we have now are
> > > > > > still plagued by the inconsistency.
> > > > > >
> > > > > > I think we always need an explicit translation step from either v4l2 or
> > > > > > drm to the internal representation and back, without ever assuming that
> > > > > > formats might be compatible because they share the same fourcc.
> > > > >
> > > > > I don't agree. APIs evolve, and while we can't switch from one set of
> > > > > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > > > > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > > > > be impopular from a userspace developers point of view there, I don't
> > > > > think we have ruled it out completely. The move to the request API is
> > > > > also an area where a common set of 4CCs could be used, as it will depart
> > > > > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > > > > yet, but I wouldn't rule it out completely for the future.
> > > > >
> > > > > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > > > > modifier.
> > > > >
> > > > > DRM modifiers are mostly about tiling and compression, and we hardly
> > > > > support these in V4L2. What are the modifiers you think are hardcoded in
> > > > > 4CCs in V4L2 ?
> > > >
> > > > Hm maybe it was a drm one that didn't come from v4l or anywhere else
> > > > really, but the NV12MT one is nv12 + some tiling. I think we managed to
> > > > uapi-bend that one into shape in at least drm.
> > >
> > > The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
> > > to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
> > > pretty similar case to the Mediatek one indeed.
> > >
> > > In our cause, that's because the video decoding engine produces its
> > > destination buffers in a specific tiled format, that the display engine
> > > can take in directly.
> >
> > We also have the Samsung tiling (Z pattern) as mentioned here, but also
> > linear 16x16 tile placement (also from Samsung ?) and I believe Amlogic
> > CODEC patches is bringing another tiling (unavoidable on older Meson8,
> > with 64bytes swaps). All these should be expressed as NV12 + mod in DRM
> > space.
> >
> > What is very often not enabled, but affect the performance on mainline
> > media drivers is the ARM frame buffer compression. I know that RK chips
> > have support for this, and that you can't achieve the maximum
> > throughput without that. This one is not documented anywhere, but I
> > understand that there is multiple variants that HW vendor licence.
> > Though, in general, each SoC are likely running a single variant, so a
> > single mod would make sense.
>
> We have AFBC modifiers now in drm_fourcc.h, jointly developed by
> display engineers from ARM and mali gpu reverse engineer people doing
> the panfrost driver. So should be covered.
>
> > So all this to say that V4L2 equally needs supports for these. What I
> > understood through DRM API is that a buffer allocated for let's say
> > NV12 + mod, is compatible with linear NV12. That could be used to
> > simplify some code, but at the same time, a common API that deals with
> > the padding and alignment of each format + mod independently would do
> > that same as long as this is not variable depending on which target HW
> > uses that same format.
>
> Not sure why you mean with NV12 + mod is compatible with linear NV12.
> In general fourcc + modifier != fourcc = linear modifier, size, number
> of planes, alignment constraints and everything else can be changed by
> a modifier (and there's examples for all of these, maybe not yet in
> all cases for NV12, but I think NV12 + AFBC modifiers gives some
> pretty interesting results). In generally you need to think of the
> (drm fourcc, modifier) as the pair identified the pixel format, each
> part individually is fairly meanigless. We have lots of modifiers
> where the exact tiling mode/layout changes depending upon the fourcc
> code.

I only meant that the NV12 + mod have the same number of planes, and
should be large enough to store a linear NV12 equivalent. Not that it
would render correctly (even though I found it useful to be able to
render them when I needed to reverse it).

>
> The only exception is legacy interfaces, i.e. when you create a
> framebuffer with only the drm fourcc and not a modifier. In that case
> you get driver specific behaviour, but modifier aware drivers tend to
> change that into a specific (fourcc, modifier) pair again (at least
> i915.ko, and it's what I recommend).
>
> Oh and we have some legacy modifiers that depend upon the target hw,
> but it's very much not recommended (we did it in i915 to make things
> easier on really old platforms, on some of them we don't even know the
> exact tiling mode since it's not documented nor correctly
> reverse-engineered).
>
> Another fun case are some of the recent non-byte-aligned formats, for
> which you need to have a modifier to be able to use them with anything
> - there's not really a real linear layout for them, they just serve as
> an index/parameter into the modifier space.
>
> > I think DRM + mod reduce the amount of dedicated formats that needs to
> > be added, and simplify the documentation of each formats. I was looking
> > at the Amlogic Axi configurations on Amlogic S905x recently, and for
> > each well known format, there is a bitmask that let you do arbitrary
> > swapping of bits, so effectively if we start exposing all these with
> > V4L2 style, the list would become very long and hard to maintained.
>
> See above, modifiers aren't really simple ...
> -Daniel
>
> > > Cheers,
> > >
> > > Paul
> > >
> > > > -Daniel
> > > >
> > > > > > I think Boris (CCed) is working to change that by allowing to
> > > > > > pass a DRM modifier through V4L2. With that, we'd be in a situation
> > > > > > where some formats are described by the v4l2 pixfmt alone and some
> > > > > > formats are also described a modifier (but I looked at it from a
> > > > > > distance so might have misunderstod). That feels better since it avoids
> > > > > > the combinatory explosion from describing each format + modifier
> > > > > > individually.
> > > > > >
> > > > > > What do you think?
> > > > > >
> > > > > > > > v4l tends to conflate pixel format with stuff that we tend to encode
> > > > > > > > in modifiers a lot more.
> > > > > > >
> > > > > > > Boris is working on adding the modifiers concept to v4l2, so we're
> > > > > > > converging here, and we can totally have a layer in v4l2 to convert
> > > > > > > between old v4l2 "format+modifiers" formats, and DRM style formats.
> > > > > > >
> > > > > > > > There's a bunch of reasons we can't just use v4l, and they're as
> > > > > > > > valid as ever:
> > > > > > > >
> > > > > > > > - We overlap badly in some areas, so even if fourcc codes match, we
> > > > > > > > can't use them and need a duplicated DRM_FOURCC code.
> > > > > > >
> > > > > > > Do yo have an example of one of those areas?
> > > > > > >
> > > > > > > > - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > > > > > > > e.g. offset for planar yuv formats, or tiling mode
> > > > > > >
> > > > > > > As I was saying, this changes on the v4l2 side, and converging to
> > > > > > > what DRM is doing.
> > > > > > >
> > > > > > > > - drm fourcc code doesn't actually define the drm_format_info
> > > > > > > > uniquely, drivers can override that (that's an explicit design
> > > > > > > > intent of modifiers, to allow drivers to add another plane for
> > > > > > > > e.g. compression information). You'd need to pull that driver
> > > > > > > > knowledge into your format library.
> > > > > > >
> > > > > > > I'm not sure how my patches are changing anything here. This is
> > > > > > > litterally the same code, with the functions renamed.
> > > > > > >
> > > > > > > If drivers want to override that, then yeah, fine, we can let them do
> > > > > > > that. Just like any helper this just provides a default that covers
> > > > > > > most of the cases.
> > > > > > >
> > > > > > > > Iow there's no way we can easily adopt v4l fourcc, except if we do
> > > > > > > > something like a new addfb flag.
> > > > > > >
> > > > > > > For the formats that would be described as a modifier, sure. For all
> > > > > > > the others (that are not yet supported by DRM), then I don't really
> > > > > > > see why not.
> > > > > > >
> > > > > > > > > And given how the current state is a mess in this regard, I'm not too
> > > > > > > > > optimistic about keeping the formats in their relevant frameworks.
> > > > > > > > >
> > > > > > > > > Having a shared library, governed by both, will make this far easier,
> > > > > > > > > since it will be easy to discover the formats that are already
> > > > > > > > > supported by the other subsystem.
> > > > > > > >
> > > > > > > > I think a compat library that (tries to, best effort) convert between
> > > > > > > > v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > > > > > > > to the conversion functions for videomode <-> drm_display_mode
> > > > > > > > perhaps. That should be useful for drivers.
> > > > > > >
> > > > > > > That's not really what this series is about though. That series is
> > > > > > > about sharing the (image|pixels) formats database across everyone so
> > > > > > > that everyone can benefit from it.
> > > > > > >
> > > > > > > > Unifying the formats themselves, and all the associated metadata is
> > > > > > > > imo a no-go, and was a pretty conscious decision when we implemented
> > > > > > > > drm_fourcc a few years back.
> > > > > > > >
> > > > > > > > > If we want to keep the current library in DRM, we have two options
> > > > > > > > > then:
> > > > > > > > >
> > > > > > > > > - Support all the v4l2 formats in the DRM library, which is
> > > > > > > > > essentially what I'm doing in the last patches. However, that
> > > > > > > > > would require to have the v4l2 developpers also reviewing stuff
> > > > > > > > > there. And given how busy they are, I cannot really see how that
> > > > > > > > > would work.
> > > > > > > >
> > > > > > > > Well, if we end up with a common library then yes we need cross
> > > > > > > > review. There's no way around that. Doesn't matter where exactly that
> > > > > > > > library is in the filesystem tree, and adding a special MAINTAINERS
> > > > > > > > entry for anything related to fourcc (both drm and v4l) to make sure
> > > > > > > > they get cross-posted is easy. No file renaming needed.
> > > > > > >
> > > > > > > That would create some governing issues as well. For example, if you
> > > > > > > ever have a patch from one fourcc addition (that might or might not be
> > > > > > > covered by v4l2), will you wait for any v4l2 developper to review it?
> > > > > > >
> > > > > > > If it's shared code, then it should be shared, and every client
> > > > > > > framework put on an equal footing.
> > > > > > >
> > > > > > > > > - Develop the same library from within v4l2. That is really a poor
> > > > > > > > > solution, since the information would be greatly duplicated
> > > > > > > > > between the two, and in terms of maintainance, code, and binary
> > > > > > > > > size that would be duplicated too.
> > > > > > > >
> > > > > > > > It's essentially what we decided to do for drm years back.
> > > > > > >
> > > > > > > And it was probably the right solution back then, but I'm really not
> > > > > > > convinced it's still the right thing to do today.
> > > > > > >
> > > > > > > > > Having it shared allows to easily share, and discover formats from the
> > > > > > > > > other subsystem, and to have a single, unique place where this is
> > > > > > > > > centralized.
> > > > > > > >
> > > > > > > > What I think could work as middle ground:
> > > > > > > > - Put drm_format stuff into a separate .ko
> > > > > > > > - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > > > > > > > posted to both drm and v4l lists. Easy on the drm side, since it's all
> > > > > > > > separate files. Not sure it's so convenient for v4l uapi.
> > > > > > > > - Add a conversion library that tries to best-effort map between drm
> > > > > > > > and v4l formats. On the drm side that most likely means you need
> > > > > > > > offsets for planes, and modifiers too (since those are implied in some
> > > > > > > > v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > > > > > > > the drivers that use this library need.
> > > > > > > > - Add drm_fourcc as-needed by these drivers that want to use a unified
> > > > > > > > format space.
> > > > > > > >
> > > > > > > > Forcing this unification on everyone otoh is imo way too much.
> > > > > > >
> > > > > > > v4l2 is starting to converge with DRM, and we're using the DRM API
> > > > > > > pretty much untouched for that library, so I'm not really sure how
> > > > > > > anyone is hurt by that unification.
> > > > >
> > > > > --
> > > > > Regards,
> > > > >
> > > > > Laurent Pinchart
>
>


Attachments:
signature.asc (201.00 B)
This is a digitally signed message part

2019-04-23 19:07:51

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Tue, Apr 23, 2019 at 7:17 PM Nicolas Dufresne <[email protected]> wrote:
>
> Le mardi 23 avril 2019 à 17:09 +0200, Daniel Vetter a écrit :
> > On Tue, Apr 23, 2019 at 4:28 PM Nicolas Dufresne <[email protected]> wrote:
> > > Le mardi 23 avril 2019 à 14:33 +0200, Paul Kocialkowski a écrit :
> > > > Hi,
> > > >
> > > > On Tue, 2019-04-23 at 09:30 +0200, Daniel Vetter wrote:
> > > > > On Sun, Apr 21, 2019 at 01:40:45AM +0300, Laurent Pinchart wrote:
> > > > > > Hi Paul,
> > > > > >
> > > > > > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> > > > > > > On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> > > > > > > > On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > > > > > > > > And a lot of people pushed for the "fourcc is a standard", when
> > > > > > > > > really it's totally not.
> > > > > > > >
> > > > > > > > Even if it's not a standard, having consistency would be a good thing.
> > > > > > > >
> > > > > > > > And you said yourself that DRM fourcc is now pretty much an authority
> > > > > > > > for the fourcc, so it definitely looks like a standard to me.
> > > > > > >
> > > > > > > I think trying to make the V4L2 and DRM fourccs converge is a lost
> > > > > > > cause, as it has already significantly diverged. Even if we coordinate
> > > > > > > an effort to introduce new formats with the same fourcc on both sides,
> > > > > > > I don't see what good that would be since the formats we have now are
> > > > > > > still plagued by the inconsistency.
> > > > > > >
> > > > > > > I think we always need an explicit translation step from either v4l2 or
> > > > > > > drm to the internal representation and back, without ever assuming that
> > > > > > > formats might be compatible because they share the same fourcc.
> > > > > >
> > > > > > I don't agree. APIs evolve, and while we can't switch from one set of
> > > > > > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > > > > > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > > > > > be impopular from a userspace developers point of view there, I don't
> > > > > > think we have ruled it out completely. The move to the request API is
> > > > > > also an area where a common set of 4CCs could be used, as it will depart
> > > > > > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > > > > > yet, but I wouldn't rule it out completely for the future.
> > > > > >
> > > > > > > It looks like so far, V4L2 pixel formats describe a DRM pixel format +
> > > > > > > modifier.
> > > > > >
> > > > > > DRM modifiers are mostly about tiling and compression, and we hardly
> > > > > > support these in V4L2. What are the modifiers you think are hardcoded in
> > > > > > 4CCs in V4L2 ?
> > > > >
> > > > > Hm maybe it was a drm one that didn't come from v4l or anywhere else
> > > > > really, but the NV12MT one is nv12 + some tiling. I think we managed to
> > > > > uapi-bend that one into shape in at least drm.
> > > >
> > > > The one I had in mind is V4L2_PIX_FMT_SUNXI_TILED_NV12 which translates
> > > > to DRM_FORMAT_NV12 + DRM_FORMAT_MOD_ALLWINNER_TILED. Seems to be a
> > > > pretty similar case to the Mediatek one indeed.
> > > >
> > > > In our cause, that's because the video decoding engine produces its
> > > > destination buffers in a specific tiled format, that the display engine
> > > > can take in directly.
> > >
> > > We also have the Samsung tiling (Z pattern) as mentioned here, but also
> > > linear 16x16 tile placement (also from Samsung ?) and I believe Amlogic
> > > CODEC patches is bringing another tiling (unavoidable on older Meson8,
> > > with 64bytes swaps). All these should be expressed as NV12 + mod in DRM
> > > space.
> > >
> > > What is very often not enabled, but affect the performance on mainline
> > > media drivers is the ARM frame buffer compression. I know that RK chips
> > > have support for this, and that you can't achieve the maximum
> > > throughput without that. This one is not documented anywhere, but I
> > > understand that there is multiple variants that HW vendor licence.
> > > Though, in general, each SoC are likely running a single variant, so a
> > > single mod would make sense.
> >
> > We have AFBC modifiers now in drm_fourcc.h, jointly developed by
> > display engineers from ARM and mali gpu reverse engineer people doing
> > the panfrost driver. So should be covered.
> >
> > > So all this to say that V4L2 equally needs supports for these. What I
> > > understood through DRM API is that a buffer allocated for let's say
> > > NV12 + mod, is compatible with linear NV12. That could be used to
> > > simplify some code, but at the same time, a common API that deals with
> > > the padding and alignment of each format + mod independently would do
> > > that same as long as this is not variable depending on which target HW
> > > uses that same format.
> >
> > Not sure why you mean with NV12 + mod is compatible with linear NV12.
> > In general fourcc + modifier != fourcc = linear modifier, size, number
> > of planes, alignment constraints and everything else can be changed by
> > a modifier (and there's examples for all of these, maybe not yet in
> > all cases for NV12, but I think NV12 + AFBC modifiers gives some
> > pretty interesting results). In generally you need to think of the
> > (drm fourcc, modifier) as the pair identified the pixel format, each
> > part individually is fairly meanigless. We have lots of modifiers
> > where the exact tiling mode/layout changes depending upon the fourcc
> > code.
>
> I only meant that the NV12 + mod have the same number of planes, and
> should be large enough to store a linear NV12 equivalent. Not that it
> would render correctly (even though I found it useful to be able to
> render them when I needed to reverse it).

It might be this assumption still holds for nv12, but we've definitely
broken it for other fourcc. You can't rely on this at least being
universally true.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-04-23 19:20:27

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Tue, Apr 23, 2019 at 5:45 PM Laurent Pinchart
<[email protected]> wrote:
>
> Hi Daniel,
>
> On Tue, Apr 23, 2019 at 09:25:54AM +0200, Daniel Vetter wrote:
> > On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> > > On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> > >> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> > >>> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > >>>> On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> > >>>>> On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > >>>>>> On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > >>>>>>> Hi,
> > >>>>>>>
> > >>>>>>> DRM comes with an extensive format support to retrieve the various
> > >>>>>>> parameters associated with a given format (such as the subsampling, or the
> > >>>>>>> bits per pixel), as well as some helpers and utilities to ease the driver
> > >>>>>>> development.
> > >>>>>>>
> > >>>>>>> v4l2, on the other side, doesn't provide such facilities, leaving each
> > >>>>>>> driver reimplement a subset of the formats parameters for the one supported
> > >>>>>>> by that particular driver. This leads to a lot of duplication and
> > >>>>>>> boilerplate code in the v4l2 drivers.
> > >>>>>>>
> > >>>>>>> This series tries to address this by moving the DRM format API into lib and
> > >>>>>>> turning it into a more generic API. In order to do this, we've needed to do
> > >>>>>>> some preliminary changes on the DRM drivers, then moved the API and finally
> > >>>>>>> converted a v4l2 driver to give an example of how such library could be
> > >>>>>>> used.
> > >>>>>>>
> > >>>>>>> Let me know what you think,
> > >>>>>>> Maxime
> > >>>>>>>
> > >>>>>>> Changes from RFC:
> > >>>>>>> - Rebased on next
> > >>>>>>> - Fixed the various formats mapping
> > >>>>>>> - Added tags
> > >>>>>>> - Did most of the formats functions as inline functions
> > >>>>>>> - Used a consistent prefix for all the utilities functions
> > >>>>>>> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > >>>>>>> arm64 and x86_64
> > >>>>>>> - Fixed out of array bounds warnings in the image_format_info_block_*
> > >>>>>>> functions
> > >>>>>>> - Added License and copyright headers on missing files
> > >>>>>>>
> > >>>>>>> Maxime Ripard (20):
> > >>>>>>> drm: Remove users of drm_format_num_planes
> > >>>>>>> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > >>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > >>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > >>>>>>> drm: Replace instances of drm_format_info by drm_get_format_info
> > >>>>>>> lib: Add video format information library
> > >>>>>>> drm/fb: Move from drm_format_info to image_format_info
> > >>>>>>> drm/malidp: Convert to generic image format library
> > >>>>>>> drm/client: Convert to generic image format library
> > >>>>>>> drm/exynos: Convert to generic image format library
> > >>>>>>> drm/i915: Convert to generic image format library
> > >>>>>>> drm/ipuv3: Convert to generic image format library
> > >>>>>>> drm/msm: Convert to generic image format library
> > >>>>>>> drm/omap: Convert to generic image format library
> > >>>>>>> drm/rockchip: Convert to generic image format library
> > >>>>>>> drm/tegra: Convert to generic image format library
> > >>>>>>> drm/fourcc: Remove old DRM format API
> > >>>>>>> lib: image-formats: Add v4l2 formats support
> > >>>>>>> lib: image-formats: Add more functions
> > >>>>>>> media: sun6i: Convert to the image format API
> > >>>>>>
> > >>>>>> In the interest of making myself unpopular: Why move this out of drm?
> > >>>>>>
> > >>>>>> We do have a bunch of other such shared helpers already (mostly in
> > >>>>>> drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > >>>>>> sure that's going better than keeping it maintained in drm.
> > >
> > > That's a bit of a different situation as both DRM and FBDEV address the
> > > same features (display output), and FBDEV is deprecared and replaced by
> > > DRM.
> > >
> > > I'm not against maintaining a 4CC library in DRM (adding a third-party
> > > maintainer would likely create more problems than it would solve), but
> > > that doesn't mean the library has to live in drivers/gpu/, nor that it
> > > needs to have the drm_ prefix. I would actually advocate to make it live
> > > in a neutral directory, with a neutral prefix (kudos to anyone who can
> > > propose a nice naming convention that would establish a new shared
> > > ground for image/video-related Linux APIs), and maintained through the
> > > DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> > > reaches all the related folks).
> > >
> > >>>>>> Plus the uapi is already that you include drm_fourcc.h to get at these,
> > >>>>>> dropping the drm prefix isn't going to help I think.
> > >>>>>>
> > >>>>>> Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > >>>>>> use it without dragging in all of drm), and we need to add some fields for
> > >>>>>> converting to v4l fourcc codes (which are different). But that should be
> > >>>>>> all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > >>>>>> it's actually a feature: It makes it really clear that these are the drm
> > >>>>>> fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > >>>>>> that. That allocation authority is also already baked into various khr/ext
> > >>>>>> standards, too.
> > >
> > > There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> > > documentation. Look at
> > > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> > > or
> > > https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> > > for instance. It's painful to write, painful to read, but defines the
> > > 4CCs very clearly without ambiguity. I wouldn't be surprised if
> > > different drivers used the same DRM 4CC for different formats due to the
> > > lack of detailed documentation. Moving to a shared library for 4CCs
> > > should also address the documentation side, and any new format added to
> > > the kernel, whether from the V4L2 side or the DRM side, would be
> > > required to provide detailed documentation. That would be a great
> > > improvement for DRM 4CC handling.
> > >
> > >>>>> The way I see it, there's a fundamental difference between the UAPI
> > >>>>> and the kernel. I don't suggest we change anything about the UAPI: the
> > >>>>> drm formats should keep their prefix, drm_fourcc.h can remain that
> > >>>>> authority, it's all fine.
> > >>>>>
> > >>>>> Internally however, the long term goal is to share the fourcc's
> > >>>>> between DRM and V4L2 for the same formats. It basically means that of
> > >>>>> course v4l2 should be using the DRM fourcc when a format exists in DRM
> > >>>>> and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > >>>>> exists in v4l2 but not DRM, and that is far more likely, given the
> > >>>>> already extensive v4l2 formats support.
> > >>>>
> > >>>> Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > >>>> format identifier space.
> > >>>
> > >>> No to what exactly?
> > >>>
> > >>>> And a lot of people pushed for the "fourcc is a standard", when
> > >>>> really it's totally not.
> > >>>
> > >>> Even if it's not a standard, having consistency would be a good thing.
> > >>>
> > >>> And you said yourself that DRM fourcc is now pretty much an authority
> > >>> for the fourcc, so it definitely looks like a standard to me.
> > >>
> > >> drm fourcc is the authority for drm fourcc codes. Not for any of the
> > >> others (and there's lots of them). Now it's used in a bunch of other
> > >> places (khr standards, dri protocols in wayland/X11), but they're
> > >> still only drm fourcc. There is no overall fourcc standard.
> > >>
> > >>>> v4l tends to conflate pixel format with stuff that we tend to encode
> > >>>> in modifiers a lot more.
> > >>>
> > >>> Boris is working on adding the modifiers concept to v4l2, so we're
> > >>> converging here, and we can totally have a layer in v4l2 to convert
> > >>> between old v4l2 "format+modifiers" formats, and DRM style formats.
> > >>>
> > >>>> There's a bunch of reasons we can't just use v4l, and they're as
> > >>>> valid as ever:
> > >>>>
> > >>>> - We overlap badly in some areas, so even if fourcc codes match, we
> > >>>> can't use them and need a duplicated DRM_FOURCC code.
> > >>>
> > >>> Do yo have an example of one of those areas?
> > >>
> > >> I think the rgb stuff was one of the big reasons to not reuse any
> > >> existing fourcc standard (whether v4l, or another one from e.g. video
> > >> container formats). We had initial patches to reuse the fourcc that
> > >> existed, but the end result was really inconsistent, so we ditch that
> > >> and rolled out a new set of entirely drm specific fourcc codes for
> > >> rgba.
> > >
> > > Could you give one or a couple of examples of V4L2 4CCs that are not
> > > OCD-compatible ? :-)
> > >
> > >>>> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > >>>> e.g. offset for planar yuv formats, or tiling mode
> > >>>
> > >>> As I was saying, this changes on the v4l2 side, and converging to
> > >>> what DRM is doing.
> > >>>
> > >>>> - drm fourcc code doesn't actually define the drm_format_info
> > >>>> uniquely, drivers can override that (that's an explicit design
> > >>>> intent of modifiers, to allow drivers to add another plane for
> > >>>> e.g. compression information). You'd need to pull that driver
> > >>>> knowledge into your format library.
> > >
> > > That's a mistake in my opinion. We tried that in V4L2 to store metadata
> > > in a separate plane, and had to go another route eventually as it
> > > created a very bad mess.
> >
> > Just quick clarification in the middle here: This is how the hw works.
>
> The hardware takes parameters from a buffer, but it doesn't mandate how
> that buffer is exposed to userspace :-) Using an extra plane is one
> option, but other APIs are possible.

I think Daniel Stone explains fairly well why some of our additional
metadata is included as a plane, while a lot of the other metadata
involved in rendering/compute the framebuffer isn't. Not really
anything to add here.

> > It's not metadata that sw ever touches (in general, testcases to make sure
> > we display these correctly excepted).
> >
> > There has been some talking to add maybe a bit more mixed metadata, for
> > fast-clear colors (which isn't used by any display engine afaik yet). That
>
> What are fast-clear colors ?

hw offers enormous amounts of tricks to make glClear O(1), or at least
close enough. glClear is usually what's done at the start of every
frame, and clears the entire framebuffer to a uniform color. This is
achieved usually through 3 pieces:
- actual framebuffer plane with the pixel data
- a 2nd plane that (usually, but there's lots of tricks here) contains
a bit of metadata per cacheline/block/whatever in the framebuffer to
indicate how/if those pixels are compressed, or whether they are still
the uniform color supplied through glClear. For actual O(1) this
metadata is hierarchical, so that a glClear really only sets the
top-level metadata to "all subordinate blocks still have are the clear
color". hw tends to have some pretty strong opinions on where it's
going to look for that 2nd plane.
- curiously on most hw the actual clear color is supplied separately
(and our plan is to just stuff it into a 3rd plane)

> > would generally be written by the cpu (in the gl stack), but again read by
> > the hw (loaded as indirect state packet most likely, or something like
> > that). So again hw specific layout, because the hw needs to read it.
> >
> > Pure metadata only of interest for the cpu/sw stack has been shot down
> > completely on the drm side too.
> >
> > > There's a tendency in both subsystems to look at the other as a bit of a
> > > retarded relative, and that's a shame, we have lots to learn from each
> > > other's mistakes. That wouldn't be too difficult if people started
> > > talking to each other.
> > >
> > > A semi-related comment: DRM also carries other mistakes of its own, I'm
> > > thinking about DRM_FORMAT_BIG_ENDIAN in particular
> >
> > Yeah that one is hilarios, but in practice big endian is dead, except for
> > a very few server chips, and there I think Gerd's work mostly fixed up
> > that mess.
> >
> > >>> I'm not sure how my patches are changing anything here. This is
> > >>> litterally the same code, with the functions renamed.
> > >>>
> > >>> If drivers want to override that, then yeah, fine, we can let them do
> > >>> that. Just like any helper this just provides a default that covers
> > >>> most of the cases.
> > >>>
> > >>>> Iow there's no way we can easily adopt v4l fourcc, except if we do
> > >>>> something like a new addfb flag.
> > >>>
> > >>> For the formats that would be described as a modifier, sure. For all
> > >>> the others (that are not yet supported by DRM), then I don't really
> > >>> see why not.
> > >>
> > >> See above, we tried that initially, didn't pass the ocd tests when
> > >> reviewing. Maybe the situation is better outside of rbgx/a formats,
> > >> and I think we do at least try to use the same fourcc codes there when
> > >> there already is one. But then the details occasionally look
> > >> different.
> > >>
> > >>>>> And given how the current state is a mess in this regard, I'm not too
> > >>>>> optimistic about keeping the formats in their relevant frameworks.
> > >>>>>
> > >>>>> Having a shared library, governed by both, will make this far easier,
> > >>>>> since it will be easy to discover the formats that are already
> > >>>>> supported by the other subsystem.
> > >>>>
> > >>>> I think a compat library that (tries to, best effort) convert between
> > >>>> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > >>>> to the conversion functions for videomode <-> drm_display_mode
> > >>>> perhaps. That should be useful for drivers.
> > >>>
> > >>> That's not really what this series is about though. That series is
> > >>> about sharing the (image|pixels) formats database across everyone so
> > >>> that everyone can benefit from it.
> > >>
> > >> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> > >> would be good, since there's really no standard here.
> > >>
> > >>>> Unifying the formats themselves, and all the associated metadata is
> > >>>> imo a no-go, and was a pretty conscious decision when we implemented
> > >>>> drm_fourcc a few years back.
> > >>>>
> > >>>>> If we want to keep the current library in DRM, we have two options
> > >>>>> then:
> > >>>>>
> > >>>>> - Support all the v4l2 formats in the DRM library, which is
> > >>>>> essentially what I'm doing in the last patches. However, that
> > >>>>> would require to have the v4l2 developpers also reviewing stuff
> > >>>>> there. And given how busy they are, I cannot really see how that
> > >>>>> would work.
> > >>>>
> > >>>> Well, if we end up with a common library then yes we need cross
> > >>>> review. There's no way around that. Doesn't matter where exactly that
> > >>>> library is in the filesystem tree, and adding a special MAINTAINERS
> > >>>> entry for anything related to fourcc (both drm and v4l) to make sure
> > >>>> they get cross-posted is easy. No file renaming needed.
> > >>>
> > >>> That would create some governing issues as well. For example, if you
> > >>> ever have a patch from one fourcc addition (that might or might not be
> > >>> covered by v4l2), will you wait for any v4l2 developper to review it?
> > >>
> > >> None of this is fixed by code renaming or locations. Either way we
> > >> need to figure that out.
> > >>
> > >> And yes part of the reasons for not moving this out of drm is that I'm
> > >> not a fan of boutique trees for small stuff. If sharing means we need
> > >> to split the drm_fourcc code and library out of drm trees, I'm not
> > >> sure that's a good idea. We're already super liberal with merging
> > >> anything through driver trees with acks, and integrating them quickly
> > >> into drm-next. This would still be workable if v4l sends regular pull
> > >> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > >> do). If we can only sync up once per merge window with a shared
> > >> boutique tree for formats only, life is going to be painful.
> > >
> > > That should be solved by the proposal above, maintaining the shared
> > > library in the DRM tree. We would need to be careful there, and ideally
> > > maintain that in a separate branch that could be merged in both DRM and
> > > V4L2 without having to merge most of the other subsystem's pending
> > > changes at the same time, but I think it's doable without any big issue.
> > >
> > >>> If it's shared code, then it should be shared, and every client
> > >>> framework put on an equal footing.
> > >>>
> > >>>>> - Develop the same library from within v4l2. That is really a poor
> > >>>>> solution, since the information would be greatly duplicated
> > >>>>> between the two, and in terms of maintainance, code, and binary
> > >>>>> size that would be duplicated too.
> > >>>>
> > >>>> It's essentially what we decided to do for drm years back.
> > >>>
> > >>> And it was probably the right solution back then, but I'm really not
> > >>> convinced it's still the right thing to do today.
> > >>>
> > >>>>> Having it shared allows to easily share, and discover formats from the
> > >>>>> other subsystem, and to have a single, unique place where this is
> > >>>>> centralized.
> > >>>>
> > >>>> What I think could work as middle ground:
> > >>>> - Put drm_format stuff into a separate .ko
> > >>>> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > >>>> posted to both drm and v4l lists. Easy on the drm side, since it's all
> > >>>> separate files. Not sure it's so convenient for v4l uapi.
> > >>>> - Add a conversion library that tries to best-effort map between drm
> > >>>> and v4l formats. On the drm side that most likely means you need
> > >>>> offsets for planes, and modifiers too (since those are implied in some
> > >>>> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > >>>> the drivers that use this library need.
> > >>>> - Add drm_fourcc as-needed by these drivers that want to use a unified
> > >>>> format space.
> > >>>>
> > >>>> Forcing this unification on everyone otoh is imo way too much.
> > >>>
> > >>> v4l2 is starting to converge with DRM, and we're using the DRM API
> > >>> pretty much untouched for that library, so I'm not really sure how
> > >>> anyone is hurt by that unification.
> > >>
> > >> It might make sense to regularly pull v4l updates into drm-next then
> > >> anyway. That would also remove the need to have the format library
> > >> somewhere else.
> > >
> > > Are you saying it should the live in V4L2 ? ;-)
> >
> > Maybe a few clarifications on how the drm shared core thing usually works,
> > and why I'm a sticker here. Bottom reply since I'm not sure where to put
> > it:
> >
> > - Refactorings usually go in through drm-misc (at least since a few
> > years).
> >
> > - Small patches go in through the relevant driver tree (which is often
> > drm-misc, but not always), with an Ack from drm maintainers.
> >
> > - No topic branches, everyone just pushes patches where it's most
> > convenient.
> >
> > We get away with this mess because everyone sends regular pull requests to
> > drm, where the entire history is baked in and others can backmerge/fast
> > forward/rebase. Worst case you wait one month (around the merge window,
> > when drm-next is closed for features), but usually it's just 1-2 weeks.
> > Plus we tend to have fairly big trees, with good chances that the next
> > patch series lands in the same tree again and no work at all is needed.
> >
> > If we start regularly sharing lots of code with v4l (which seems to be the
> > long term goal here), then I think we need something equally convenient
> > for all that.
> >
> > We're not going to be able to teach some complicated topic branch scheme
> > to the 50+ submaintainers/committers we have in drm - a lot much more
> > basic stuff already takes lots of work to get it to stick. If the proposal
> > is "to be careful" and "maintain it in a separate branch", I'm not in
> > favour because I think that just wouldn't work.
>
> Why not ? It can be a fast-moving branch that gets merged in drm-misc
> as often as you want (even at every commit if that's desired). We're
> dealing with a limited amount of code here, and there's no more reason
> that V4L2 should pull in drm-misc to get 4CC updates than DRM should
> pull V4L2 for the same. I have no objection against a 4CC branch being
> officially maintained under the DRM umbrella, but I think the code
> should live elsewhere than drivers/gpu/drm/, have a neutral prefix, and
> not require pulling an entire subsystem in.

I think small boutique trees are a problem themselves, not a solution.
So if you're creating a new small boutique tree to fix a problem, you
then have 2. Yes, assuming sufficient expenditure of energy it can be
made to work, but I'd prefer to make my own life as easy and lazy as
possible :-) And I think I've been fairly successful at that within
drivers/gpu at least.

Imo the proper fix is to merge v4l and drm, at a process/maintainer
level. That would solve both the original issue and the 2ndary one of
the permanent topic branch.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2019-05-02 08:25:28

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH 18/20] lib: image-formats: Add v4l2 formats support

Hi Maxime,

On 4/17/19 9:54 AM, Maxime Ripard wrote:
> V4L2 uses different fourcc's than DRM, and has a different set of formats.
> For now, let's add the v4l2 fourcc's for the already existing formats.

For this lib to be more useful for V4L2, would it be a good idea to add
Bayer formats as well? This can be done in a separate patch.

Those formats are V4L specific, but are very common.

Regards,

Hans

>
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> include/linux/image-formats.h | 9 +++++-
> lib/image-formats.c | 62 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 71 insertions(+)
>
> diff --git a/include/linux/image-formats.h b/include/linux/image-formats.h
> index ec43d9f9a527..b78b8e861fc9 100644
> --- a/include/linux/image-formats.h
> +++ b/include/linux/image-formats.h
> @@ -50,6 +50,13 @@ struct image_format_info {
> };
>
> /**
> + * @v4l2_fmt:
> + *
> + * V4L2 4CC format identifier (V4L2_PIX_FMT_*)
> + */
> + u32 v4l2_fmt;
> +
> + /**
> * @depth:
> *
> * Color depth (number of bits per pixel excluding padding bits),
> @@ -382,6 +389,8 @@ uint64_t image_format_info_min_pitch(const struct image_format_info *info,
> }
>
> const struct image_format_info *__image_format_drm_lookup(u32 drm);
> +const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2);
> const struct image_format_info *image_format_drm_lookup(u32 drm);
> +const struct image_format_info *image_format_v4l2_lookup(u32 v4l2);
>
> #endif /* _IMAGE_FORMATS_H_ */
> diff --git a/lib/image-formats.c b/lib/image-formats.c
> index 1e52a7410222..25fa22d243fb 100644
> --- a/lib/image-formats.c
> +++ b/lib/image-formats.c
> @@ -25,12 +25,14 @@
> #include <linux/image-formats.h>
> #include <linux/kernel.h>
> #include <linux/math64.h>
> +#include <linux/videodev2.h>
>
> #include <uapi/drm/drm_fourcc.h>
>
> static const struct image_format_info formats[] = {
> {
> .drm_fmt = DRM_FORMAT_C8,
> + .v4l2_fmt = V4L2_PIX_FMT_GREY,
> .depth = 8,
> .num_planes = 1,
> .cpp = { 1, 0, 0 },
> @@ -38,6 +40,7 @@ static const struct image_format_info formats[] = {
> .vsub = 1,
> }, {
> .drm_fmt = DRM_FORMAT_RGB332,
> + .v4l2_fmt = V4L2_PIX_FMT_RGB332,
> .depth = 8,
> .num_planes = 1,
> .cpp = { 1, 0, 0 },
> @@ -172,6 +175,7 @@ static const struct image_format_info formats[] = {
> .has_alpha = true,
> }, {
> .drm_fmt = DRM_FORMAT_RGB565,
> + .v4l2_fmt = V4L2_PIX_FMT_RGB565X,
> .depth = 16,
> .num_planes = 1,
> .cpp = { 2, 0, 0 },
> @@ -186,6 +190,7 @@ static const struct image_format_info formats[] = {
> .vsub = 1,
> }, {
> .drm_fmt = DRM_FORMAT_RGB888,
> + .v4l2_fmt = V4L2_PIX_FMT_BGR24,
> .depth = 24,
> .num_planes = 1,
> .cpp = { 3, 0, 0 },
> @@ -193,6 +198,7 @@ static const struct image_format_info formats[] = {
> .vsub = 1,
> }, {
> .drm_fmt = DRM_FORMAT_BGR888,
> + .v4l2_fmt = V4L2_PIX_FMT_RGB24,
> .depth = 24,
> .num_planes = 1,
> .cpp = { 3, 0, 0 },
> @@ -200,6 +206,7 @@ static const struct image_format_info formats[] = {
> .vsub = 1,
> }, {
> .drm_fmt = DRM_FORMAT_XRGB8888,
> + .v4l2_fmt = V4L2_PIX_FMT_XBGR32,
> .depth = 24,
> .num_planes = 1,
> .cpp = { 4, 0, 0 },
> @@ -304,6 +311,7 @@ static const struct image_format_info formats[] = {
> .has_alpha = true,
> }, {
> .drm_fmt = DRM_FORMAT_ARGB8888,
> + .v4l2_fmt = V4L2_PIX_FMT_ABGR32,
> .depth = 32,
> .num_planes = 1,
> .cpp = { 4, 0, 0 },
> @@ -384,6 +392,7 @@ static const struct image_format_info formats[] = {
> .has_alpha = true,
> }, {
> .drm_fmt = DRM_FORMAT_YUV410,
> + .v4l2_fmt = V4L2_PIX_FMT_YUV410,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -392,6 +401,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YVU410,
> + .v4l2_fmt = V4L2_PIX_FMT_YVU410,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -416,6 +426,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YUV420,
> + .v4l2_fmt = V4L2_PIX_FMT_YUV420,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -424,6 +435,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YVU420,
> + .v4l2_fmt = V4L2_PIX_FMT_YVU420,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -432,6 +444,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YUV422,
> + .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -448,6 +461,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YUV444,
> + .v4l2_fmt = V4L2_PIX_FMT_YUV444,
> .depth = 0,
> .num_planes = 3,
> .cpp = { 1, 1, 1 },
> @@ -464,6 +478,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV12,
> + .v4l2_fmt = V4L2_PIX_FMT_NV12,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -472,6 +487,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV21,
> + .v4l2_fmt = V4L2_PIX_FMT_NV21,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -480,6 +496,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV16,
> + .v4l2_fmt = V4L2_PIX_FMT_NV16,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -488,6 +505,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV61,
> + .v4l2_fmt = V4L2_PIX_FMT_NV61,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -496,6 +514,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV24,
> + .v4l2_fmt = V4L2_PIX_FMT_NV24,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -504,6 +523,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_NV42,
> + .v4l2_fmt = V4L2_PIX_FMT_NV42,
> .depth = 0,
> .num_planes = 2,
> .cpp = { 1, 2, 0 },
> @@ -512,6 +532,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YUYV,
> + .v4l2_fmt = V4L2_PIX_FMT_YUYV,
> .depth = 0,
> .num_planes = 1,
> .cpp = { 2, 0, 0 },
> @@ -520,6 +541,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_YVYU,
> + .v4l2_fmt = V4L2_PIX_FMT_YVYU,
> .depth = 0,
> .num_planes = 1,
> .cpp = { 2, 0, 0 },
> @@ -528,6 +550,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_UYVY,
> + .v4l2_fmt = V4L2_PIX_FMT_UYVY,
> .depth = 0,
> .num_planes = 1,
> .cpp = { 2, 0, 0 },
> @@ -536,6 +559,7 @@ static const struct image_format_info formats[] = {
> .is_yuv = true,
> }, {
> .drm_fmt = DRM_FORMAT_VYUY,
> + .v4l2_fmt = V4L2_PIX_FMT_VYUY,
> .depth = 0,
> .num_planes = 1,
> .cpp = { 2, 0, 0 },
> @@ -653,3 +677,41 @@ const struct image_format_info *image_format_drm_lookup(u32 drm)
> return format;
> }
> EXPORT_SYMBOL(image_format_drm_lookup);
> +
> +/**
> + * __image_format_v4l2_lookup - query information for a given format
> + * @v4l2: V4L2 fourcc pixel format (V4L2_PIX_FMT_*)
> + *
> + * The caller should only pass a supported pixel format to this function.
> + *
> + * Returns:
> + * The instance of struct image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *__image_format_v4l2_lookup(u32 v4l2)
> +{
> + return __image_format_lookup(v4l2_fmt, v4l2);
> +}
> +EXPORT_SYMBOL(__image_format_v4l2_lookup);
> +
> +/**
> + * image_format_v4l2_lookup - query information for a given format
> + * @v4l2: V4L2 fourcc pixel format (V4L2_PIX_FMT_*)
> + *
> + * 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 image_format_info that describes the pixel format, or
> + * NULL if the format is unsupported.
> + */
> +const struct image_format_info *image_format_v4l2_lookup(u32 v4l2)
> +{
> + const struct image_format_info *format;
> +
> + format = __image_format_v4l2_lookup(v4l2);
> +
> + WARN_ON(!format);
> + return format;
> +}
> +EXPORT_SYMBOL(image_format_v4l2_lookup);
>

2019-05-02 08:28:12

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Maxime,

Apologies for the late reply, most if this thread happened when I was on
vacation, and I missed that I should reply to it. Thank you for reminding
me.

Please let me know if I should reply to other mails in the discussion of
this patch series.

On 4/18/19 10:56 PM, Maxime Ripard wrote:
> On Thu, Apr 18, 2019 at 02:32:14PM +0200, Daniel Vetter wrote:
>>>>>> Unifying the formats themselves, and all the associated metadata is
>>>>>> imo a no-go, and was a pretty conscious decision when we implemented
>>>>>> drm_fourcc a few years back.
>>>>>>
>>>>>>> If we want to keep the current library in DRM, we have two options
>>>>>>> then:
>>>>>>>
>>>>>>> - Support all the v4l2 formats in the DRM library, which is
>>>>>>> essentially what I'm doing in the last patches. However, that
>>>>>>> would require to have the v4l2 developpers also reviewing stuff
>>>>>>> there. And given how busy they are, I cannot really see how that
>>>>>>> would work.
>>>>>>
>>>>>> Well, if we end up with a common library then yes we need cross
>>>>>> review. There's no way around that. Doesn't matter where exactly that
>>>>>> library is in the filesystem tree, and adding a special MAINTAINERS
>>>>>> entry for anything related to fourcc (both drm and v4l) to make sure
>>>>>> they get cross-posted is easy. No file renaming needed.
>>>>>
>>>>> That would create some governing issues as well. For example, if you
>>>>> ever have a patch from one fourcc addition (that might or might not be
>>>>> covered by v4l2), will you wait for any v4l2 developper to review it?
>>>>
>>>> None of this is fixed by code renaming or locations. Either way we
>>>> need to figure that out.
>>>>
>>>> And yes part of the reasons for not moving this out of drm is that I'm
>>>> not a fan of boutique trees for small stuff. If sharing means we need
>>>> to split the drm_fourcc code and library out of drm trees, I'm not
>>>> sure that's a good idea. We're already super liberal with merging
>>>> anything through driver trees with acks, and integrating them quickly
>>>> into drm-next. This would still be workable if v4l sends regular pull
>>>> requests to drm-next (every 1-2 weeks, like the other big gpu trees
>>>> do). If we can only sync up once per merge window with a shared
>>>> boutique tree for formats only, life is going to be painful.
>>>
>>> I don't get why we want to turn DRM into some kind of a black hole
>>> that would pull everything. We don't have to, really. And at the same
>>> time it carries the message that v4l2 is less important than DRM for
>>> some reason, which I'm really not comfortable with.
>>
>> Make another tree somewhere that pulls in trees more often than every
>> merge window, and I'm happy. It's the coordination effort of lots of
>> trees that creates the black hole, not the other way round. Yes topic
>> trees work, but if topic trees are persistent something with the
>> organization of trees is wrong and needs to change. This very much
>> looks like we'll end up with a perpetual topic branch for format stuff
>> between drm and v4l.
>
> Well, if v4l2 sends a PR to DRM every 1 or 2 weeks, that definitely
> looks like a topic branch to me. And on a far more frequent basis than
> when we will merge a format description.
>
>> The other shared stuff (like hdmi infoframes) seems to change a lot
>> less often, so the occasional patch hasn't been a pain. But drm_fourcc
>> related stuff sees a lot of work, both in adding new formats and in
>> refactoring the library to keep up with all the new use-cases.
>
> When was the last time a refactoring that changed the API happened?
>
> Most of the changes will be new format descriptions, and I guess that
> would only concern a single tree.
>
> And really, we're doing this all the time, so I'm not sure what the
> big deal is here.
>
> I feel like there's something that you don't really like about this,
> but you're not saying this out loud.
>
> Sure, the exact process needs to be figured out, and everyone needs to
> agree upon that process. But that's pretty much it, and it's nothing
> out of the ordinary.
>
>> And yes I think an overall gfx-like-stuff.git tree for drm and v4l and
>> the few other bits really makes tons of sense. Not as a tree where
>> people commit, but as the 2nd-level integration tree (like drm.git
>> right now for gpu stuff).
>>
>>> And I don't really get why you're against this in the first
>>> place. When you have some code in a single driver that would benefit
>>> more driver, you create a helper and move it into the core.
>>
>> It's a feature that drm doesn't share that much code with other parts
>> of the kernel, it makes backporting the gfx stack to lts kernels a lot
>> easier. Until someone fixes the upstream kernel release model to no
>> longer need large scale gpu driver backports, we need to keep that.
>>
>>> In this case, we have some code used by a framework that more
>>> framework could use, and we move it to a core-er place. How is that
>>> different?
>>
>> Imo core sharing for code sharing's sake is overrated. If we already
>> have drm and v4l tightly integrated as a community, then code sharing
>> becomes a lot easier, and a lot more reasonable to do.
>
> At least Laurent, Boris, Ezequiel, Gustavo and I have been working on
> v4l2, so I'm not sure how not integrated we are.
>
>> Plus we can then just stuff code int drivers/gpu or drivers/video
>> (or merge these two because really it's all the same). But my
>> understanding is that integrating more tightly with the drm folks is
>> a very contreversial topic in v4l
>
> So, I sent the RFC expecting that kind of feedback.
>
> Hans replied mainly to that patch https://patchwork.freedesktop.org/patch/293043/
>
> "
> If we are creating a common library then I think we should change that rule
> to: "unless they are in use by a DRM or V4L2 driver". And when new formats are
> added, and they exists already for DRM or V4L2, then we should use the same
> fourcc for the other subsystem.
>
> I.e. if pixelformat V4L2_PIX_FMT_FOO was already defined, then add a:
>
> #define DRM_FORMAT_FOO V4L2_PIX_FMT_FOO
>
> rather than creating a new fourcc.
>
> We could even start looking at redoing the whole scheme in a unified way, but
> that's something for the (far) future.
>
> This is already a big step forward.
> "
>
> So, not controversial at all.
>
>> and until that's resolved I don't see a huge need or benefit in
>> sharing tons of code.
>
> That's mostly tons of data though. The code is pretty small and
> trivial.
>
>> And the format stuff is a lot more central to kms than e.g. the
>> infoframe helpers.
>>
>> Au contraire, I think forcing this has a lot of potential for
>> needless fights between drm and v4l.
>
> We're all reasonable, so I'm not sure why we would need to fight here.
>
>> Hence my suggestion to try a minimal format conversion library
>> between the drm format world and the v4l format wolrd, and see how
>> that goes. That contains a lot less risk than going all in right
>> from the start.
>
> And it's really not about getting access to the DRM fourcc. It's about
> getting access to DRM's format description, so I'm not really sure
> what there is to convert, we just want a lookup.

I see this patch series as a first step towards further integration
between drm/v4l (at least in this area). That said, the V4L API has some
serious limitations at the moment when it comes to describing these formats,
and until that is fixed there is no point in doing more than what this series
does. I certainly don't expect a lot of patches, and I am happy for drm to
maintain this for now.

Work has started on improving how V4L2 handles formats (1) but this will take
quite some time before this is ready. In part because we are working on
things that have a higher prio (HW codec support). But the intention is to
become much closer to how drm handles this to simplify format matching between
the two subsystems.

Once that's in place (next year?) it will become much more interesting to
look at further integration between drm and v4l.

Note that that is just my personal opinion. Others may very well disagree.

So in my view this series is a first solid step towards further integration.
And initially it should be fine to have the most common formats available in
this new lib. That should solve most of the current problems.

Regards,

Hans

(1) https://www.mail-archive.com/[email protected]/msg146075.html

2019-05-06 13:24:34

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 18/20] lib: image-formats: Add v4l2 formats support

Hi Hans

On Thu, May 02, 2019 at 10:24:00AM +0200, Hans Verkuil wrote:
> On 4/17/19 9:54 AM, Maxime Ripard wrote:
> > V4L2 uses different fourcc's than DRM, and has a different set of formats.
> > For now, let's add the v4l2 fourcc's for the already existing formats.
>
> For this lib to be more useful for V4L2, would it be a good idea to add
> Bayer formats as well? This can be done in a separate patch.
>
> Those formats are V4L specific, but are very common.

Yeah, this was mostly to support the formats that are already
supported as of today, but eventually more are going to be supported,
and the bayer formats seems like a natural choice :)

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Attachments:
(No filename) (765.00 B)
signature.asc (235.00 B)
Download all attachments

2019-05-11 19:21:03

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Paul,

On Tue, Apr 23, 2019 at 06:54:49PM +0200, Paul Kocialkowski wrote:
> Le dimanche 21 avril 2019 à 01:40 +0300, Laurent Pinchart a écrit :
> > On Thu, Apr 18, 2019 at 01:49:54PM +0200, Paul Kocialkowski wrote:
> >> On Thu, 2019-04-18 at 11:02 +0200, Maxime Ripard wrote:
> >>> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> >>>> And a lot of people pushed for the "fourcc is a standard", when
> >>>> really it's totally not.
> >>>
> >>> Even if it's not a standard, having consistency would be a good thing.
> >>>
> >>> And you said yourself that DRM fourcc is now pretty much an authority
> >>> for the fourcc, so it definitely looks like a standard to me.
> >>
> >> I think trying to make the V4L2 and DRM fourccs converge is a lost
> >> cause, as it has already significantly diverged. Even if we coordinate
> >> an effort to introduce new formats with the same fourcc on both sides,
> >> I don't see what good that would be since the formats we have now are
> >> still plagued by the inconsistency.
> >>
> >> I think we always need an explicit translation step from either v4l2 or
> >> drm to the internal representation and back, without ever assuming that
> >> formats might be compatible because they share the same fourcc.
> >
> > I don't agree. APIs evolve, and while we can't switch from one set of
> > 4CCs to another in existing APIs, we could in new APIs. Boris is working
> > on new ioctls to handle formats in V4L2, and while 4CC unification could
> > be impopular from a userspace developers point of view there, I don't
> > think we have ruled it out completely. The move to the request API is
> > also an area where a common set of 4CCs could be used, as it will depart
> > from the existing V4L2 ioctls. To summarize my opinion, we're not there
> > yet, but I wouldn't rule it out completely for the future.
>
> Well, I don't see how we could maintain backward compatibility with
> some DRM and V4L2 fourccs that are compatible and some that aren't.
> Since both descriptions have diverged already, one would need explicit
> checking of whether the format at hand is a compatible one or not
> before passing-it along as-is to the other subsystem or going through a
> format conversion step (in userspace, duplicating the information).
> So it feels like it kind of defeats the purpose.

Yes and no. If a V4L2-only application needs to deal with two sets of
4CCs for old and new APIs, it's a burden. However, if an application
that shares buffers between V4L2 and DRM/KMS can use a single set of
4CCs, that's a win, as those applications already need to convert. In
the end this shifts the problem from one set of applications to another,
but as soon as the new APIs get old enough to mandate their usage (which
would roughly be when the corresponding kernel ships in all supported
versions of all major distros), then applications will be able to drop
the conversion code, and everybody will be happier. Short term pain for
long term gain.

> If we're going to use a unified 4CC representation in the future, I
> think we should do it by using the new formats that this proposal is
> introducing instead of subsystem-specific formats. At which point I
> believe we will need an internal conversion step between that format
> and what the subsystem uses internally. Or do it the other way round
> and use the unified format all around the subsystem, with a legacy
> layer for the previous subsystem-specific format.

I agree with you. I would like new APIs to use unified 4CCs (probably
coming from DRM), and have an internal conversion from and to
subsystem-specific 4CCs where needed. That's quite a lot of work of
course, and won't happen overnight.

--
Regards,

Laurent Pinchart

2019-05-11 19:28:00

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Hi Daniel,

On Tue, Apr 23, 2019 at 09:18:52PM +0200, Daniel Vetter wrote:
> On Tue, Apr 23, 2019 at 5:45 PM Laurent Pinchart wrote:
> > On Tue, Apr 23, 2019 at 09:25:54AM +0200, Daniel Vetter wrote:
> >> On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> >>> On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> >>>> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> >>>>> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> >>>>>> On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> >>>>>>> On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> >>>>>>>> On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> >>>>>>>>> Hi,
> >>>>>>>>>
> >>>>>>>>> DRM comes with an extensive format support to retrieve the various
> >>>>>>>>> parameters associated with a given format (such as the subsampling, or the
> >>>>>>>>> bits per pixel), as well as some helpers and utilities to ease the driver
> >>>>>>>>> development.
> >>>>>>>>>
> >>>>>>>>> v4l2, on the other side, doesn't provide such facilities, leaving each
> >>>>>>>>> driver reimplement a subset of the formats parameters for the one supported
> >>>>>>>>> by that particular driver. This leads to a lot of duplication and
> >>>>>>>>> boilerplate code in the v4l2 drivers.
> >>>>>>>>>
> >>>>>>>>> This series tries to address this by moving the DRM format API into lib and
> >>>>>>>>> turning it into a more generic API. In order to do this, we've needed to do
> >>>>>>>>> some preliminary changes on the DRM drivers, then moved the API and finally
> >>>>>>>>> converted a v4l2 driver to give an example of how such library could be
> >>>>>>>>> used.
> >>>>>>>>>
> >>>>>>>>> Let me know what you think,
> >>>>>>>>> Maxime
> >>>>>>>>>
> >>>>>>>>> Changes from RFC:
> >>>>>>>>> - Rebased on next
> >>>>>>>>> - Fixed the various formats mapping
> >>>>>>>>> - Added tags
> >>>>>>>>> - Did most of the formats functions as inline functions
> >>>>>>>>> - Used a consistent prefix for all the utilities functions
> >>>>>>>>> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> >>>>>>>>> arm64 and x86_64
> >>>>>>>>> - Fixed out of array bounds warnings in the image_format_info_block_*
> >>>>>>>>> functions
> >>>>>>>>> - Added License and copyright headers on missing files
> >>>>>>>>>
> >>>>>>>>> Maxime Ripard (20):
> >>>>>>>>> drm: Remove users of drm_format_num_planes
> >>>>>>>>> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> >>>>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> >>>>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> >>>>>>>>> drm: Replace instances of drm_format_info by drm_get_format_info
> >>>>>>>>> lib: Add video format information library
> >>>>>>>>> drm/fb: Move from drm_format_info to image_format_info
> >>>>>>>>> drm/malidp: Convert to generic image format library
> >>>>>>>>> drm/client: Convert to generic image format library
> >>>>>>>>> drm/exynos: Convert to generic image format library
> >>>>>>>>> drm/i915: Convert to generic image format library
> >>>>>>>>> drm/ipuv3: Convert to generic image format library
> >>>>>>>>> drm/msm: Convert to generic image format library
> >>>>>>>>> drm/omap: Convert to generic image format library
> >>>>>>>>> drm/rockchip: Convert to generic image format library
> >>>>>>>>> drm/tegra: Convert to generic image format library
> >>>>>>>>> drm/fourcc: Remove old DRM format API
> >>>>>>>>> lib: image-formats: Add v4l2 formats support
> >>>>>>>>> lib: image-formats: Add more functions
> >>>>>>>>> media: sun6i: Convert to the image format API
> >>>>>>>>
> >>>>>>>> In the interest of making myself unpopular: Why move this out of drm?
> >>>>>>>>
> >>>>>>>> We do have a bunch of other such shared helpers already (mostly in
> >>>>>>>> drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> >>>>>>>> sure that's going better than keeping it maintained in drm.
> >>>
> >>> That's a bit of a different situation as both DRM and FBDEV address the
> >>> same features (display output), and FBDEV is deprecared and replaced by
> >>> DRM.
> >>>
> >>> I'm not against maintaining a 4CC library in DRM (adding a third-party
> >>> maintainer would likely create more problems than it would solve), but
> >>> that doesn't mean the library has to live in drivers/gpu/, nor that it
> >>> needs to have the drm_ prefix. I would actually advocate to make it live
> >>> in a neutral directory, with a neutral prefix (kudos to anyone who can
> >>> propose a nice naming convention that would establish a new shared
> >>> ground for image/video-related Linux APIs), and maintained through the
> >>> DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> >>> reaches all the related folks).
> >>>
> >>>>>>>> Plus the uapi is already that you include drm_fourcc.h to get at these,
> >>>>>>>> dropping the drm prefix isn't going to help I think.
> >>>>>>>>
> >>>>>>>> Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> >>>>>>>> use it without dragging in all of drm), and we need to add some fields for
> >>>>>>>> converting to v4l fourcc codes (which are different). But that should be
> >>>>>>>> all possible. And I don't think the drm_ prefix in v4l code is a problem,
> >>>>>>>> it's actually a feature: It makes it really clear that these are the drm
> >>>>>>>> fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> >>>>>>>> that. That allocation authority is also already baked into various khr/ext
> >>>>>>>> standards, too.
> >>>
> >>> There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> >>> documentation. Look at
> >>> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> >>> or
> >>> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> >>> for instance. It's painful to write, painful to read, but defines the
> >>> 4CCs very clearly without ambiguity. I wouldn't be surprised if
> >>> different drivers used the same DRM 4CC for different formats due to the
> >>> lack of detailed documentation. Moving to a shared library for 4CCs
> >>> should also address the documentation side, and any new format added to
> >>> the kernel, whether from the V4L2 side or the DRM side, would be
> >>> required to provide detailed documentation. That would be a great
> >>> improvement for DRM 4CC handling.
> >>>
> >>>>>>> The way I see it, there's a fundamental difference between the UAPI
> >>>>>>> and the kernel. I don't suggest we change anything about the UAPI: the
> >>>>>>> drm formats should keep their prefix, drm_fourcc.h can remain that
> >>>>>>> authority, it's all fine.
> >>>>>>>
> >>>>>>> Internally however, the long term goal is to share the fourcc's
> >>>>>>> between DRM and V4L2 for the same formats. It basically means that of
> >>>>>>> course v4l2 should be using the DRM fourcc when a format exists in DRM
> >>>>>>> and not v4l2, but also that DRM should use v4l2 fourcc when the format
> >>>>>>> exists in v4l2 but not DRM, and that is far more likely, given the
> >>>>>>> already extensive v4l2 formats support.
> >>>>>>
> >>>>>> Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> >>>>>> format identifier space.
> >>>>>
> >>>>> No to what exactly?
> >>>>>
> >>>>>> And a lot of people pushed for the "fourcc is a standard", when
> >>>>>> really it's totally not.
> >>>>>
> >>>>> Even if it's not a standard, having consistency would be a good thing.
> >>>>>
> >>>>> And you said yourself that DRM fourcc is now pretty much an authority
> >>>>> for the fourcc, so it definitely looks like a standard to me.
> >>>>
> >>>> drm fourcc is the authority for drm fourcc codes. Not for any of the
> >>>> others (and there's lots of them). Now it's used in a bunch of other
> >>>> places (khr standards, dri protocols in wayland/X11), but they're
> >>>> still only drm fourcc. There is no overall fourcc standard.
> >>>>
> >>>>>> v4l tends to conflate pixel format with stuff that we tend to encode
> >>>>>> in modifiers a lot more.
> >>>>>
> >>>>> Boris is working on adding the modifiers concept to v4l2, so we're
> >>>>> converging here, and we can totally have a layer in v4l2 to convert
> >>>>> between old v4l2 "format+modifiers" formats, and DRM style formats.
> >>>>>
> >>>>>> There's a bunch of reasons we can't just use v4l, and they're as
> >>>>>> valid as ever:
> >>>>>>
> >>>>>> - We overlap badly in some areas, so even if fourcc codes match, we
> >>>>>> can't use them and need a duplicated DRM_FOURCC code.
> >>>>>
> >>>>> Do yo have an example of one of those areas?
> >>>>
> >>>> I think the rgb stuff was one of the big reasons to not reuse any
> >>>> existing fourcc standard (whether v4l, or another one from e.g. video
> >>>> container formats). We had initial patches to reuse the fourcc that
> >>>> existed, but the end result was really inconsistent, so we ditch that
> >>>> and rolled out a new set of entirely drm specific fourcc codes for
> >>>> rgba.
> >>>
> >>> Could you give one or a couple of examples of V4L2 4CCs that are not
> >>> OCD-compatible ? :-)
> >>>
> >>>>>> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> >>>>>> e.g. offset for planar yuv formats, or tiling mode
> >>>>>
> >>>>> As I was saying, this changes on the v4l2 side, and converging to
> >>>>> what DRM is doing.
> >>>>>
> >>>>>> - drm fourcc code doesn't actually define the drm_format_info
> >>>>>> uniquely, drivers can override that (that's an explicit design
> >>>>>> intent of modifiers, to allow drivers to add another plane for
> >>>>>> e.g. compression information). You'd need to pull that driver
> >>>>>> knowledge into your format library.
> >>>
> >>> That's a mistake in my opinion. We tried that in V4L2 to store metadata
> >>> in a separate plane, and had to go another route eventually as it
> >>> created a very bad mess.
> >>
> >> Just quick clarification in the middle here: This is how the hw works.
> >
> > The hardware takes parameters from a buffer, but it doesn't mandate how
> > that buffer is exposed to userspace :-) Using an extra plane is one
> > option, but other APIs are possible.
>
> I think Daniel Stone explains fairly well why some of our additional
> metadata is included as a plane, while a lot of the other metadata
> involved in rendering/compute the framebuffer isn't. Not really
> anything to add here.
>
> >> It's not metadata that sw ever touches (in general, testcases to make sure
> >> we display these correctly excepted).
> >>
> >> There has been some talking to add maybe a bit more mixed metadata, for
> >> fast-clear colors (which isn't used by any display engine afaik yet). That
> >
> > What are fast-clear colors ?
>
> hw offers enormous amounts of tricks to make glClear O(1), or at least
> close enough. glClear is usually what's done at the start of every
> frame, and clears the entire framebuffer to a uniform color. This is
> achieved usually through 3 pieces:
> - actual framebuffer plane with the pixel data
> - a 2nd plane that (usually, but there's lots of tricks here) contains
> a bit of metadata per cacheline/block/whatever in the framebuffer to
> indicate how/if those pixels are compressed, or whether they are still
> the uniform color supplied through glClear. For actual O(1) this
> metadata is hierarchical, so that a glClear really only sets the
> top-level metadata to "all subordinate blocks still have are the clear
> color". hw tends to have some pretty strong opinions on where it's
> going to look for that 2nd plane.
> - curiously on most hw the actual clear color is supplied separately
> (and our plan is to just stuff it into a 3rd plane)

Just to clarify, is this needed for display engines ? Does the GPU
render to a 3 planes buffer with glClear()-related data in planes 2 and
3, with the buffer then being passed to the display engine that knows
how to interpret this, or are those extra planes only needed for GPU
rendering ?

> >> would generally be written by the cpu (in the gl stack), but again read by
> >> the hw (loaded as indirect state packet most likely, or something like
> >> that). So again hw specific layout, because the hw needs to read it.
> >>
> >> Pure metadata only of interest for the cpu/sw stack has been shot down
> >> completely on the drm side too.
> >>
> >>> There's a tendency in both subsystems to look at the other as a bit of a
> >>> retarded relative, and that's a shame, we have lots to learn from each
> >>> other's mistakes. That wouldn't be too difficult if people started
> >>> talking to each other.
> >>>
> >>> A semi-related comment: DRM also carries other mistakes of its own, I'm
> >>> thinking about DRM_FORMAT_BIG_ENDIAN in particular
> >>
> >> Yeah that one is hilarios, but in practice big endian is dead, except for
> >> a very few server chips, and there I think Gerd's work mostly fixed up
> >> that mess.
> >>
> >>>>> I'm not sure how my patches are changing anything here. This is
> >>>>> litterally the same code, with the functions renamed.
> >>>>>
> >>>>> If drivers want to override that, then yeah, fine, we can let them do
> >>>>> that. Just like any helper this just provides a default that covers
> >>>>> most of the cases.
> >>>>>
> >>>>>> Iow there's no way we can easily adopt v4l fourcc, except if we do
> >>>>>> something like a new addfb flag.
> >>>>>
> >>>>> For the formats that would be described as a modifier, sure. For all
> >>>>> the others (that are not yet supported by DRM), then I don't really
> >>>>> see why not.
> >>>>
> >>>> See above, we tried that initially, didn't pass the ocd tests when
> >>>> reviewing. Maybe the situation is better outside of rbgx/a formats,
> >>>> and I think we do at least try to use the same fourcc codes there when
> >>>> there already is one. But then the details occasionally look
> >>>> different.
> >>>>
> >>>>>>> And given how the current state is a mess in this regard, I'm not too
> >>>>>>> optimistic about keeping the formats in their relevant frameworks.
> >>>>>>>
> >>>>>>> Having a shared library, governed by both, will make this far easier,
> >>>>>>> since it will be easy to discover the formats that are already
> >>>>>>> supported by the other subsystem.
> >>>>>>
> >>>>>> I think a compat library that (tries to, best effort) convert between
> >>>>>> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> >>>>>> to the conversion functions for videomode <-> drm_display_mode
> >>>>>> perhaps. That should be useful for drivers.
> >>>>>
> >>>>> That's not really what this series is about though. That series is
> >>>>> about sharing the (image|pixels) formats database across everyone so
> >>>>> that everyone can benefit from it.
> >>>>
> >>>> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> >>>> would be good, since there's really no standard here.
> >>>>
> >>>>>> Unifying the formats themselves, and all the associated metadata is
> >>>>>> imo a no-go, and was a pretty conscious decision when we implemented
> >>>>>> drm_fourcc a few years back.
> >>>>>>
> >>>>>>> If we want to keep the current library in DRM, we have two options
> >>>>>>> then:
> >>>>>>>
> >>>>>>> - Support all the v4l2 formats in the DRM library, which is
> >>>>>>> essentially what I'm doing in the last patches. However, that
> >>>>>>> would require to have the v4l2 developpers also reviewing stuff
> >>>>>>> there. And given how busy they are, I cannot really see how that
> >>>>>>> would work.
> >>>>>>
> >>>>>> Well, if we end up with a common library then yes we need cross
> >>>>>> review. There's no way around that. Doesn't matter where exactly that
> >>>>>> library is in the filesystem tree, and adding a special MAINTAINERS
> >>>>>> entry for anything related to fourcc (both drm and v4l) to make sure
> >>>>>> they get cross-posted is easy. No file renaming needed.
> >>>>>
> >>>>> That would create some governing issues as well. For example, if you
> >>>>> ever have a patch from one fourcc addition (that might or might not be
> >>>>> covered by v4l2), will you wait for any v4l2 developper to review it?
> >>>>
> >>>> None of this is fixed by code renaming or locations. Either way we
> >>>> need to figure that out.
> >>>>
> >>>> And yes part of the reasons for not moving this out of drm is that I'm
> >>>> not a fan of boutique trees for small stuff. If sharing means we need
> >>>> to split the drm_fourcc code and library out of drm trees, I'm not
> >>>> sure that's a good idea. We're already super liberal with merging
> >>>> anything through driver trees with acks, and integrating them quickly
> >>>> into drm-next. This would still be workable if v4l sends regular pull
> >>>> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> >>>> do). If we can only sync up once per merge window with a shared
> >>>> boutique tree for formats only, life is going to be painful.
> >>>
> >>> That should be solved by the proposal above, maintaining the shared
> >>> library in the DRM tree. We would need to be careful there, and ideally
> >>> maintain that in a separate branch that could be merged in both DRM and
> >>> V4L2 without having to merge most of the other subsystem's pending
> >>> changes at the same time, but I think it's doable without any big issue.
> >>>
> >>>>> If it's shared code, then it should be shared, and every client
> >>>>> framework put on an equal footing.
> >>>>>
> >>>>>>> - Develop the same library from within v4l2. That is really a poor
> >>>>>>> solution, since the information would be greatly duplicated
> >>>>>>> between the two, and in terms of maintainance, code, and binary
> >>>>>>> size that would be duplicated too.
> >>>>>>
> >>>>>> It's essentially what we decided to do for drm years back.
> >>>>>
> >>>>> And it was probably the right solution back then, but I'm really not
> >>>>> convinced it's still the right thing to do today.
> >>>>>
> >>>>>>> Having it shared allows to easily share, and discover formats from the
> >>>>>>> other subsystem, and to have a single, unique place where this is
> >>>>>>> centralized.
> >>>>>>
> >>>>>> What I think could work as middle ground:
> >>>>>> - Put drm_format stuff into a separate .ko
> >>>>>> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> >>>>>> posted to both drm and v4l lists. Easy on the drm side, since it's all
> >>>>>> separate files. Not sure it's so convenient for v4l uapi.
> >>>>>> - Add a conversion library that tries to best-effort map between drm
> >>>>>> and v4l formats. On the drm side that most likely means you need
> >>>>>> offsets for planes, and modifiers too (since those are implied in some
> >>>>>> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> >>>>>> the drivers that use this library need.
> >>>>>> - Add drm_fourcc as-needed by these drivers that want to use a unified
> >>>>>> format space.
> >>>>>>
> >>>>>> Forcing this unification on everyone otoh is imo way too much.
> >>>>>
> >>>>> v4l2 is starting to converge with DRM, and we're using the DRM API
> >>>>> pretty much untouched for that library, so I'm not really sure how
> >>>>> anyone is hurt by that unification.
> >>>>
> >>>> It might make sense to regularly pull v4l updates into drm-next then
> >>>> anyway. That would also remove the need to have the format library
> >>>> somewhere else.
> >>>
> >>> Are you saying it should the live in V4L2 ? ;-)
> >>
> >> Maybe a few clarifications on how the drm shared core thing usually works,
> >> and why I'm a sticker here. Bottom reply since I'm not sure where to put
> >> it:
> >>
> >> - Refactorings usually go in through drm-misc (at least since a few
> >> years).
> >>
> >> - Small patches go in through the relevant driver tree (which is often
> >> drm-misc, but not always), with an Ack from drm maintainers.
> >>
> >> - No topic branches, everyone just pushes patches where it's most
> >> convenient.
> >>
> >> We get away with this mess because everyone sends regular pull requests to
> >> drm, where the entire history is baked in and others can backmerge/fast
> >> forward/rebase. Worst case you wait one month (around the merge window,
> >> when drm-next is closed for features), but usually it's just 1-2 weeks.
> >> Plus we tend to have fairly big trees, with good chances that the next
> >> patch series lands in the same tree again and no work at all is needed.
> >>
> >> If we start regularly sharing lots of code with v4l (which seems to be the
> >> long term goal here), then I think we need something equally convenient
> >> for all that.
> >>
> >> We're not going to be able to teach some complicated topic branch scheme
> >> to the 50+ submaintainers/committers we have in drm - a lot much more
> >> basic stuff already takes lots of work to get it to stick. If the proposal
> >> is "to be careful" and "maintain it in a separate branch", I'm not in
> >> favour because I think that just wouldn't work.
> >
> > Why not ? It can be a fast-moving branch that gets merged in drm-misc
> > as often as you want (even at every commit if that's desired). We're
> > dealing with a limited amount of code here, and there's no more reason
> > that V4L2 should pull in drm-misc to get 4CC updates than DRM should
> > pull V4L2 for the same. I have no objection against a 4CC branch being
> > officially maintained under the DRM umbrella, but I think the code
> > should live elsewhere than drivers/gpu/drm/, have a neutral prefix, and
> > not require pulling an entire subsystem in.
>
> I think small boutique trees are a problem themselves, not a solution.
> So if you're creating a new small boutique tree to fix a problem, you
> then have 2. Yes, assuming sufficient expenditure of energy it can be
> made to work, but I'd prefer to make my own life as easy and lazy as
> possible :-) And I think I've been fairly successful at that within
> drivers/gpu at least.
>
> Imo the proper fix is to merge v4l and drm, at a process/maintainer
> level. That would solve both the original issue and the 2ndary one of
> the permanent topic branch.

Proposals are welcome ;-)

--
Regards,

Laurent Pinchart

2019-05-13 16:42:49

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

Em Mon, 13 May 2019 16:57:19 +0200
Daniel Vetter <[email protected]> escreveu:

> > > I think small boutique trees are a problem themselves, not a solution.
> > > So if you're creating a new small boutique tree to fix a problem, you
> > > then have 2. Yes, assuming sufficient expenditure of energy it can be
> > > made to work, but I'd prefer to make my own life as easy and lazy as
> > > possible :-) And I think I've been fairly successful at that within
> > > drivers/gpu at least.
> > >
> > > Imo the proper fix is to merge v4l and drm, at a process/maintainer
> > > level. That would solve both the original issue and the 2ndary one of
> > > the permanent topic branch.
> >
> > Proposals are welcome ;-)
>
> I'm already somewhat unpopular at LPC/lkml/kernel-at-large, I don't want
> to make this worse. That's why I don't want to officially push for
> anything here myself, nor be in any other way involved in an effort to
> figure out v4l governance and maintainership rules.
>
> What I think is required for efficient collaboration with drm (no matter
> how we implement that in the details once we're ready for that step) is
> some kind of group maintainership model. Doesn't need to be as extreme as
> drm-misc, but I think at least something like the soc tree (while it was
> still a bit more limited as arm-soc). Otherwise the impendence mismatch
> between how drm rolls and how v4l rolls is probably way too much. From my
> understanding v4l is working differently.
>
> Also, through sheer inertia of size, I don't think it'll be easier to
> align drm with the v4l model. So that option is not realistic.

I don't think it is realistic trying to align V4L2 model to every single
other subsystems we use. We have a lot of alignment with alsa, with even
increased during this merge window due to some drivers on media sharing
media controller resources with usb-audio. We also have lots of alignment
with i2c, as we use a lot of stuff there, and from time to time they
need to add new features due to our needs. The same is true also for
input and for other subsystems and arch/sub-arch trees.

That doesn't mean at all that everybody should use the same maintainership
model. Each subsystem should use whatever suits best.

That's said, after following this thread for a while, I'm starting to
convince that it wouldn't even be realistic to have a common fourcc
API for both subsystems. The internal requirements from each subsystem
are different, and, as it was already pointed in this thread, that's
basically why DRM ended by having their own way of doing that.

Yet, it would make sense to have at least a single nomenclature for
both systems to use, but it could be a simple as what we already do
with other common resources, like:

Documentation/ioctl/ioctl-number.txt

If we keep the fourcc codes there sorted, if one subsystem would
add a conflicting code, it would be easy to notice at linux-next.

Thanks,
Mauro

2019-05-13 18:35:27

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 00/20] drm: Split out the formats API and move it to a common place

On Sat, May 11, 2019 at 10:26:32PM +0300, Laurent Pinchart wrote:
> On Tue, Apr 23, 2019 at 09:18:52PM +0200, Daniel Vetter wrote:
> > On Tue, Apr 23, 2019 at 5:45 PM Laurent Pinchart wrote:
> > > On Tue, Apr 23, 2019 at 09:25:54AM +0200, Daniel Vetter wrote:
> > >> On Sun, Apr 21, 2019 at 01:59:04AM +0300, Laurent Pinchart wrote:
> > >>> On Thu, Apr 18, 2019 at 12:07:44PM +0200, Daniel Vetter wrote:
> > >>>> On Thu, Apr 18, 2019 at 11:02 AM Maxime Ripard wrote:
> > >>>>> On Thu, Apr 18, 2019 at 09:52:10AM +0200, Daniel Vetter wrote:
> > >>>>>> On Thu, Apr 18, 2019 at 8:22 AM Maxime Ripard wrote:
> > >>>>>>> On Wed, Apr 17, 2019 at 05:41:21PM +0200, Daniel Vetter wrote:
> > >>>>>>>> On Wed, Apr 17, 2019 at 09:54:26AM +0200, Maxime Ripard wrote:
> > >>>>>>>>> Hi,
> > >>>>>>>>>
> > >>>>>>>>> DRM comes with an extensive format support to retrieve the various
> > >>>>>>>>> parameters associated with a given format (such as the subsampling, or the
> > >>>>>>>>> bits per pixel), as well as some helpers and utilities to ease the driver
> > >>>>>>>>> development.
> > >>>>>>>>>
> > >>>>>>>>> v4l2, on the other side, doesn't provide such facilities, leaving each
> > >>>>>>>>> driver reimplement a subset of the formats parameters for the one supported
> > >>>>>>>>> by that particular driver. This leads to a lot of duplication and
> > >>>>>>>>> boilerplate code in the v4l2 drivers.
> > >>>>>>>>>
> > >>>>>>>>> This series tries to address this by moving the DRM format API into lib and
> > >>>>>>>>> turning it into a more generic API. In order to do this, we've needed to do
> > >>>>>>>>> some preliminary changes on the DRM drivers, then moved the API and finally
> > >>>>>>>>> converted a v4l2 driver to give an example of how such library could be
> > >>>>>>>>> used.
> > >>>>>>>>>
> > >>>>>>>>> Let me know what you think,
> > >>>>>>>>> Maxime
> > >>>>>>>>>
> > >>>>>>>>> Changes from RFC:
> > >>>>>>>>> - Rebased on next
> > >>>>>>>>> - Fixed the various formats mapping
> > >>>>>>>>> - Added tags
> > >>>>>>>>> - Did most of the formats functions as inline functions
> > >>>>>>>>> - Used a consistent prefix for all the utilities functions
> > >>>>>>>>> - Fixed the compilation breakages, and did a run of allmodconfig for arm,
> > >>>>>>>>> arm64 and x86_64
> > >>>>>>>>> - Fixed out of array bounds warnings in the image_format_info_block_*
> > >>>>>>>>> functions
> > >>>>>>>>> - Added License and copyright headers on missing files
> > >>>>>>>>>
> > >>>>>>>>> Maxime Ripard (20):
> > >>>>>>>>> drm: Remove users of drm_format_num_planes
> > >>>>>>>>> drm: Remove users of drm_format_(horz|vert)_chroma_subsampling
> > >>>>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp
> > >>>>>>>>> drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height
> > >>>>>>>>> drm: Replace instances of drm_format_info by drm_get_format_info
> > >>>>>>>>> lib: Add video format information library
> > >>>>>>>>> drm/fb: Move from drm_format_info to image_format_info
> > >>>>>>>>> drm/malidp: Convert to generic image format library
> > >>>>>>>>> drm/client: Convert to generic image format library
> > >>>>>>>>> drm/exynos: Convert to generic image format library
> > >>>>>>>>> drm/i915: Convert to generic image format library
> > >>>>>>>>> drm/ipuv3: Convert to generic image format library
> > >>>>>>>>> drm/msm: Convert to generic image format library
> > >>>>>>>>> drm/omap: Convert to generic image format library
> > >>>>>>>>> drm/rockchip: Convert to generic image format library
> > >>>>>>>>> drm/tegra: Convert to generic image format library
> > >>>>>>>>> drm/fourcc: Remove old DRM format API
> > >>>>>>>>> lib: image-formats: Add v4l2 formats support
> > >>>>>>>>> lib: image-formats: Add more functions
> > >>>>>>>>> media: sun6i: Convert to the image format API
> > >>>>>>>>
> > >>>>>>>> In the interest of making myself unpopular: Why move this out of drm?
> > >>>>>>>>
> > >>>>>>>> We do have a bunch of other such shared helpers already (mostly in
> > >>>>>>>> drivers/video) for dt videomode and hdmi infoframes, and I'm not super
> > >>>>>>>> sure that's going better than keeping it maintained in drm.
> > >>>
> > >>> That's a bit of a different situation as both DRM and FBDEV address the
> > >>> same features (display output), and FBDEV is deprecared and replaced by
> > >>> DRM.
> > >>>
> > >>> I'm not against maintaining a 4CC library in DRM (adding a third-party
> > >>> maintainer would likely create more problems than it would solve), but
> > >>> that doesn't mean the library has to live in drivers/gpu/, nor that it
> > >>> needs to have the drm_ prefix. I would actually advocate to make it live
> > >>> in a neutral directory, with a neutral prefix (kudos to anyone who can
> > >>> propose a nice naming convention that would establish a new shared
> > >>> ground for image/video-related Linux APIs), and maintained through the
> > >>> DRM tree (possibly with extra entries in MAINTAINERS to ensure it
> > >>> reaches all the related folks).
> > >>>
> > >>>>>>>> Plus the uapi is already that you include drm_fourcc.h to get at these,
> > >>>>>>>> dropping the drm prefix isn't going to help I think.
> > >>>>>>>>
> > >>>>>>>> Of course we'd need to make it a separate drm_formats.ko (so that v4l can
> > >>>>>>>> use it without dragging in all of drm), and we need to add some fields for
> > >>>>>>>> converting to v4l fourcc codes (which are different). But that should be
> > >>>>>>>> all possible. And I don't think the drm_ prefix in v4l code is a problem,
> > >>>>>>>> it's actually a feature: It makes it really clear that these are the drm
> > >>>>>>>> fourcc codes, as allocated in drm_fourcc.h, plus their modifiers, and all
> > >>>>>>>> that. That allocation authority is also already baked into various khr/ext
> > >>>>>>>> standards, too.
> > >>>
> > >>> There's one thing that V4L2 has and DRM hasn't for 4CCs: good
> > >>> documentation. Look at
> > >>> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/pixfmt-packed-rgb.html
> > >>> or
> > >>> https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html
> > >>> for instance. It's painful to write, painful to read, but defines the
> > >>> 4CCs very clearly without ambiguity. I wouldn't be surprised if
> > >>> different drivers used the same DRM 4CC for different formats due to the
> > >>> lack of detailed documentation. Moving to a shared library for 4CCs
> > >>> should also address the documentation side, and any new format added to
> > >>> the kernel, whether from the V4L2 side or the DRM side, would be
> > >>> required to provide detailed documentation. That would be a great
> > >>> improvement for DRM 4CC handling.
> > >>>
> > >>>>>>> The way I see it, there's a fundamental difference between the UAPI
> > >>>>>>> and the kernel. I don't suggest we change anything about the UAPI: the
> > >>>>>>> drm formats should keep their prefix, drm_fourcc.h can remain that
> > >>>>>>> authority, it's all fine.
> > >>>>>>>
> > >>>>>>> Internally however, the long term goal is to share the fourcc's
> > >>>>>>> between DRM and V4L2 for the same formats. It basically means that of
> > >>>>>>> course v4l2 should be using the DRM fourcc when a format exists in DRM
> > >>>>>>> and not v4l2, but also that DRM should use v4l2 fourcc when the format
> > >>>>>>> exists in v4l2 but not DRM, and that is far more likely, given the
> > >>>>>>> already extensive v4l2 formats support.
> > >>>>>>
> > >>>>>> Uh no. We did look at v4l fourcc extensively when deciding upon a drm
> > >>>>>> format identifier space.
> > >>>>>
> > >>>>> No to what exactly?
> > >>>>>
> > >>>>>> And a lot of people pushed for the "fourcc is a standard", when
> > >>>>>> really it's totally not.
> > >>>>>
> > >>>>> Even if it's not a standard, having consistency would be a good thing.
> > >>>>>
> > >>>>> And you said yourself that DRM fourcc is now pretty much an authority
> > >>>>> for the fourcc, so it definitely looks like a standard to me.
> > >>>>
> > >>>> drm fourcc is the authority for drm fourcc codes. Not for any of the
> > >>>> others (and there's lots of them). Now it's used in a bunch of other
> > >>>> places (khr standards, dri protocols in wayland/X11), but they're
> > >>>> still only drm fourcc. There is no overall fourcc standard.
> > >>>>
> > >>>>>> v4l tends to conflate pixel format with stuff that we tend to encode
> > >>>>>> in modifiers a lot more.
> > >>>>>
> > >>>>> Boris is working on adding the modifiers concept to v4l2, so we're
> > >>>>> converging here, and we can totally have a layer in v4l2 to convert
> > >>>>> between old v4l2 "format+modifiers" formats, and DRM style formats.
> > >>>>>
> > >>>>>> There's a bunch of reasons we can't just use v4l, and they're as
> > >>>>>> valid as ever:
> > >>>>>>
> > >>>>>> - We overlap badly in some areas, so even if fourcc codes match, we
> > >>>>>> can't use them and need a duplicated DRM_FOURCC code.
> > >>>>>
> > >>>>> Do yo have an example of one of those areas?
> > >>>>
> > >>>> I think the rgb stuff was one of the big reasons to not reuse any
> > >>>> existing fourcc standard (whether v4l, or another one from e.g. video
> > >>>> container formats). We had initial patches to reuse the fourcc that
> > >>>> existed, but the end result was really inconsistent, so we ditch that
> > >>>> and rolled out a new set of entirely drm specific fourcc codes for
> > >>>> rgba.
> > >>>
> > >>> Could you give one or a couple of examples of V4L2 4CCs that are not
> > >>> OCD-compatible ? :-)
> > >>>
> > >>>>>> - v4l encodes some metadata into the fourcc that we encode elsewhere,
> > >>>>>> e.g. offset for planar yuv formats, or tiling mode
> > >>>>>
> > >>>>> As I was saying, this changes on the v4l2 side, and converging to
> > >>>>> what DRM is doing.
> > >>>>>
> > >>>>>> - drm fourcc code doesn't actually define the drm_format_info
> > >>>>>> uniquely, drivers can override that (that's an explicit design
> > >>>>>> intent of modifiers, to allow drivers to add another plane for
> > >>>>>> e.g. compression information). You'd need to pull that driver
> > >>>>>> knowledge into your format library.
> > >>>
> > >>> That's a mistake in my opinion. We tried that in V4L2 to store metadata
> > >>> in a separate plane, and had to go another route eventually as it
> > >>> created a very bad mess.
> > >>
> > >> Just quick clarification in the middle here: This is how the hw works.
> > >
> > > The hardware takes parameters from a buffer, but it doesn't mandate how
> > > that buffer is exposed to userspace :-) Using an extra plane is one
> > > option, but other APIs are possible.
> >
> > I think Daniel Stone explains fairly well why some of our additional
> > metadata is included as a plane, while a lot of the other metadata
> > involved in rendering/compute the framebuffer isn't. Not really
> > anything to add here.
> >
> > >> It's not metadata that sw ever touches (in general, testcases to make sure
> > >> we display these correctly excepted).
> > >>
> > >> There has been some talking to add maybe a bit more mixed metadata, for
> > >> fast-clear colors (which isn't used by any display engine afaik yet). That
> > >
> > > What are fast-clear colors ?
> >
> > hw offers enormous amounts of tricks to make glClear O(1), or at least
> > close enough. glClear is usually what's done at the start of every
> > frame, and clears the entire framebuffer to a uniform color. This is
> > achieved usually through 3 pieces:
> > - actual framebuffer plane with the pixel data
> > - a 2nd plane that (usually, but there's lots of tricks here) contains
> > a bit of metadata per cacheline/block/whatever in the framebuffer to
> > indicate how/if those pixels are compressed, or whether they are still
> > the uniform color supplied through glClear. For actual O(1) this
> > metadata is hierarchical, so that a glClear really only sets the
> > top-level metadata to "all subordinate blocks still have are the clear
> > color". hw tends to have some pretty strong opinions on where it's
> > going to look for that 2nd plane.
> > - curiously on most hw the actual clear color is supplied separately
> > (and our plan is to just stuff it into a 3rd plane)
>
> Just to clarify, is this needed for display engines ? Does the GPU
> render to a 3 planes buffer with glClear()-related data in planes 2 and
> 3, with the buffer then being passed to the display engine that knows
> how to interpret this, or are those extra planes only needed for GPU
> rendering ?

I haven't yet seen a display engine that can scan out fast-cleared buffers
like these. Everyone can scan out compressed buffers, i.e. rgb + 2nd
auxialliary buffer with some compression metadata. But not yet with the
3rd plane.

So not relevant for display. But it is very much relevant for
uapi/drm_fourcc.h, because we'll need it for userspace interop between
different apis (vk, gl, ...) and different processes (client, compositor).
And in these standard extension texts we've officially made the kernel's
copy of that file the official registry. So these fourcc+modifier codes
will end up at least in that namespace (but maybe not in the same
library the kernel uses internally).

> > >> would generally be written by the cpu (in the gl stack), but again read by
> > >> the hw (loaded as indirect state packet most likely, or something like
> > >> that). So again hw specific layout, because the hw needs to read it.
> > >>
> > >> Pure metadata only of interest for the cpu/sw stack has been shot down
> > >> completely on the drm side too.
> > >>
> > >>> There's a tendency in both subsystems to look at the other as a bit of a
> > >>> retarded relative, and that's a shame, we have lots to learn from each
> > >>> other's mistakes. That wouldn't be too difficult if people started
> > >>> talking to each other.
> > >>>
> > >>> A semi-related comment: DRM also carries other mistakes of its own, I'm
> > >>> thinking about DRM_FORMAT_BIG_ENDIAN in particular
> > >>
> > >> Yeah that one is hilarios, but in practice big endian is dead, except for
> > >> a very few server chips, and there I think Gerd's work mostly fixed up
> > >> that mess.
> > >>
> > >>>>> I'm not sure how my patches are changing anything here. This is
> > >>>>> litterally the same code, with the functions renamed.
> > >>>>>
> > >>>>> If drivers want to override that, then yeah, fine, we can let them do
> > >>>>> that. Just like any helper this just provides a default that covers
> > >>>>> most of the cases.
> > >>>>>
> > >>>>>> Iow there's no way we can easily adopt v4l fourcc, except if we do
> > >>>>>> something like a new addfb flag.
> > >>>>>
> > >>>>> For the formats that would be described as a modifier, sure. For all
> > >>>>> the others (that are not yet supported by DRM), then I don't really
> > >>>>> see why not.
> > >>>>
> > >>>> See above, we tried that initially, didn't pass the ocd tests when
> > >>>> reviewing. Maybe the situation is better outside of rbgx/a formats,
> > >>>> and I think we do at least try to use the same fourcc codes there when
> > >>>> there already is one. But then the details occasionally look
> > >>>> different.
> > >>>>
> > >>>>>>> And given how the current state is a mess in this regard, I'm not too
> > >>>>>>> optimistic about keeping the formats in their relevant frameworks.
> > >>>>>>>
> > >>>>>>> Having a shared library, governed by both, will make this far easier,
> > >>>>>>> since it will be easy to discover the formats that are already
> > >>>>>>> supported by the other subsystem.
> > >>>>>>
> > >>>>>> I think a compat library that (tries to, best effort) convert between
> > >>>>>> v4l and drm fourcc would make sense. Somewhere in drivers/video, next
> > >>>>>> to the conversion functions for videomode <-> drm_display_mode
> > >>>>>> perhaps. That should be useful for drivers.
> > >>>>>
> > >>>>> That's not really what this series is about though. That series is
> > >>>>> about sharing the (image|pixels) formats database across everyone so
> > >>>>> that everyone can benefit from it.
> > >>>>
> > >>>> Yeah I know. I still think leaving the drm fourcc with the drm prefix
> > >>>> would be good, since there's really no standard here.
> > >>>>
> > >>>>>> Unifying the formats themselves, and all the associated metadata is
> > >>>>>> imo a no-go, and was a pretty conscious decision when we implemented
> > >>>>>> drm_fourcc a few years back.
> > >>>>>>
> > >>>>>>> If we want to keep the current library in DRM, we have two options
> > >>>>>>> then:
> > >>>>>>>
> > >>>>>>> - Support all the v4l2 formats in the DRM library, which is
> > >>>>>>> essentially what I'm doing in the last patches. However, that
> > >>>>>>> would require to have the v4l2 developpers also reviewing stuff
> > >>>>>>> there. And given how busy they are, I cannot really see how that
> > >>>>>>> would work.
> > >>>>>>
> > >>>>>> Well, if we end up with a common library then yes we need cross
> > >>>>>> review. There's no way around that. Doesn't matter where exactly that
> > >>>>>> library is in the filesystem tree, and adding a special MAINTAINERS
> > >>>>>> entry for anything related to fourcc (both drm and v4l) to make sure
> > >>>>>> they get cross-posted is easy. No file renaming needed.
> > >>>>>
> > >>>>> That would create some governing issues as well. For example, if you
> > >>>>> ever have a patch from one fourcc addition (that might or might not be
> > >>>>> covered by v4l2), will you wait for any v4l2 developper to review it?
> > >>>>
> > >>>> None of this is fixed by code renaming or locations. Either way we
> > >>>> need to figure that out.
> > >>>>
> > >>>> And yes part of the reasons for not moving this out of drm is that I'm
> > >>>> not a fan of boutique trees for small stuff. If sharing means we need
> > >>>> to split the drm_fourcc code and library out of drm trees, I'm not
> > >>>> sure that's a good idea. We're already super liberal with merging
> > >>>> anything through driver trees with acks, and integrating them quickly
> > >>>> into drm-next. This would still be workable if v4l sends regular pull
> > >>>> requests to drm-next (every 1-2 weeks, like the other big gpu trees
> > >>>> do). If we can only sync up once per merge window with a shared
> > >>>> boutique tree for formats only, life is going to be painful.
> > >>>
> > >>> That should be solved by the proposal above, maintaining the shared
> > >>> library in the DRM tree. We would need to be careful there, and ideally
> > >>> maintain that in a separate branch that could be merged in both DRM and
> > >>> V4L2 without having to merge most of the other subsystem's pending
> > >>> changes at the same time, but I think it's doable without any big issue.
> > >>>
> > >>>>> If it's shared code, then it should be shared, and every client
> > >>>>> framework put on an equal footing.
> > >>>>>
> > >>>>>>> - Develop the same library from within v4l2. That is really a poor
> > >>>>>>> solution, since the information would be greatly duplicated
> > >>>>>>> between the two, and in terms of maintainance, code, and binary
> > >>>>>>> size that would be duplicated too.
> > >>>>>>
> > >>>>>> It's essentially what we decided to do for drm years back.
> > >>>>>
> > >>>>> And it was probably the right solution back then, but I'm really not
> > >>>>> convinced it's still the right thing to do today.
> > >>>>>
> > >>>>>>> Having it shared allows to easily share, and discover formats from the
> > >>>>>>> other subsystem, and to have a single, unique place where this is
> > >>>>>>> centralized.
> > >>>>>>
> > >>>>>> What I think could work as middle ground:
> > >>>>>> - Put drm_format stuff into a separate .ko
> > >>>>>> - Add a MAINTAINERS entry to make sure all things fourcc are cross
> > >>>>>> posted to both drm and v4l lists. Easy on the drm side, since it's all
> > >>>>>> separate files. Not sure it's so convenient for v4l uapi.
> > >>>>>> - Add a conversion library that tries to best-effort map between drm
> > >>>>>> and v4l formats. On the drm side that most likely means you need
> > >>>>>> offsets for planes, and modifiers too (since those are implied in some
> > >>>>>> v4l fourcc). Emphasis on "best effort" i.e. only support as much as
> > >>>>>> the drivers that use this library need.
> > >>>>>> - Add drm_fourcc as-needed by these drivers that want to use a unified
> > >>>>>> format space.
> > >>>>>>
> > >>>>>> Forcing this unification on everyone otoh is imo way too much.
> > >>>>>
> > >>>>> v4l2 is starting to converge with DRM, and we're using the DRM API
> > >>>>> pretty much untouched for that library, so I'm not really sure how
> > >>>>> anyone is hurt by that unification.
> > >>>>
> > >>>> It might make sense to regularly pull v4l updates into drm-next then
> > >>>> anyway. That would also remove the need to have the format library
> > >>>> somewhere else.
> > >>>
> > >>> Are you saying it should the live in V4L2 ? ;-)
> > >>
> > >> Maybe a few clarifications on how the drm shared core thing usually works,
> > >> and why I'm a sticker here. Bottom reply since I'm not sure where to put
> > >> it:
> > >>
> > >> - Refactorings usually go in through drm-misc (at least since a few
> > >> years).
> > >>
> > >> - Small patches go in through the relevant driver tree (which is often
> > >> drm-misc, but not always), with an Ack from drm maintainers.
> > >>
> > >> - No topic branches, everyone just pushes patches where it's most
> > >> convenient.
> > >>
> > >> We get away with this mess because everyone sends regular pull requests to
> > >> drm, where the entire history is baked in and others can backmerge/fast
> > >> forward/rebase. Worst case you wait one month (around the merge window,
> > >> when drm-next is closed for features), but usually it's just 1-2 weeks.
> > >> Plus we tend to have fairly big trees, with good chances that the next
> > >> patch series lands in the same tree again and no work at all is needed.
> > >>
> > >> If we start regularly sharing lots of code with v4l (which seems to be the
> > >> long term goal here), then I think we need something equally convenient
> > >> for all that.
> > >>
> > >> We're not going to be able to teach some complicated topic branch scheme
> > >> to the 50+ submaintainers/committers we have in drm - a lot much more
> > >> basic stuff already takes lots of work to get it to stick. If the proposal
> > >> is "to be careful" and "maintain it in a separate branch", I'm not in
> > >> favour because I think that just wouldn't work.
> > >
> > > Why not ? It can be a fast-moving branch that gets merged in drm-misc
> > > as often as you want (even at every commit if that's desired). We're
> > > dealing with a limited amount of code here, and there's no more reason
> > > that V4L2 should pull in drm-misc to get 4CC updates than DRM should
> > > pull V4L2 for the same. I have no objection against a 4CC branch being
> > > officially maintained under the DRM umbrella, but I think the code
> > > should live elsewhere than drivers/gpu/drm/, have a neutral prefix, and
> > > not require pulling an entire subsystem in.
> >
> > I think small boutique trees are a problem themselves, not a solution.
> > So if you're creating a new small boutique tree to fix a problem, you
> > then have 2. Yes, assuming sufficient expenditure of energy it can be
> > made to work, but I'd prefer to make my own life as easy and lazy as
> > possible :-) And I think I've been fairly successful at that within
> > drivers/gpu at least.
> >
> > Imo the proper fix is to merge v4l and drm, at a process/maintainer
> > level. That would solve both the original issue and the 2ndary one of
> > the permanent topic branch.
>
> Proposals are welcome ;-)

I'm already somewhat unpopular at LPC/lkml/kernel-at-large, I don't want
to make this worse. That's why I don't want to officially push for
anything here myself, nor be in any other way involved in an effort to
figure out v4l governance and maintainership rules.

What I think is required for efficient collaboration with drm (no matter
how we implement that in the details once we're ready for that step) is
some kind of group maintainership model. Doesn't need to be as extreme as
drm-misc, but I think at least something like the soc tree (while it was
still a bit more limited as arm-soc). Otherwise the impendence mismatch
between how drm rolls and how v4l rolls is probably way too much. From my
understanding v4l is working differently.

Also, through sheer inertia of size, I don't think it'll be easier to
align drm with the v4l model. So that option is not realistic.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch