All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] GET_PLANE2 w/ i915 implementation
@ 2017-01-12  0:51 Ben Widawsky
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
                   ` (5 more replies)
  0 siblings, 6 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12  0:51 UTC (permalink / raw)
  To: Intel GFX, DRI Development; +Cc: Daniel Vetter, Ben Widawsky

This patch series implements GET_PLANE2 support for Intel platforms and defines
the new kernel UAPI. The idea was originally introduced by Kristian. Ultimately,
the purpose of the new API is to provide the ability to query per-plane
modifiers in KMS. These modifiers, which are just fb modifiers, will be used by
the client to enable optimal modifications for framebuffers. A reference
implementation in kmscube is referenced (in that code is a comment for an
optimal algorithm not implemented).

This work has been discussed on the mailing list and IRC over the last few weeks
and this is a result of the agreed changes. There is still some debate about the
UAPI, I believe, but I can firmly say that this seems entirely sufficient for
Intel platforms in the foreseeable future.

Cc: Kristian Høgsberg <krh@bitplanet.net>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
References: (ccs modifier) https://lists.freedesktop.org/archives/intel-gfx/2017-January/116022.html
References: (GBM modifiers) https://lists.freedesktop.org/archives/mesa-dev/2017-January/139284.html
References: (kmscube) https://github.com/bwidawsk/kmscube/commit/55519640f5a1a21983e267fb39e4cf48f6312ef9
References: (libdrm) https://lists.freedesktop.org/archives/dri-devel/2016-December/127942.html

Ben Widawsky (3):
  drm: Add new DRM_IOCTL_MODE_GETPLANE2
  drm/i915: Add format modifiers for Intel
  drm/i915: Add support for GET_PLANE2 CCS modifiers

 drivers/gpu/drm/arc/arcpgu_crtc.c               |   1 +
 drivers/gpu/drm/arm/hdlcd_crtc.c                |   1 +
 drivers/gpu/drm/arm/malidp_planes.c             |   2 +-
 drivers/gpu/drm/armada/armada_crtc.c            |   1 +
 drivers/gpu/drm/armada/armada_overlay.c         |   1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |   4 +-
 drivers/gpu/drm/drm_ioctl.c                     |   2 +-
 drivers/gpu/drm/drm_modeset_helper.c            |   1 +
 drivers/gpu/drm/drm_plane.c                     |  67 +++++++++++++-
 drivers/gpu/drm/drm_simple_kms_helper.c         |   3 +
 drivers/gpu/drm/exynos/exynos_drm_plane.c       |   2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |   1 +
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |   2 +-
 drivers/gpu/drm/i915/intel_display.c            | 116 +++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_sprite.c             |  31 +++++++
 drivers/gpu/drm/imx/ipuv3-plane.c               |   4 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c        |   2 +-
 drivers/gpu/drm/meson/meson_plane.c             |   1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |   2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |   2 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.c               |   2 +-
 drivers/gpu/drm/nouveau/nv50_display.c          |   5 +-
 drivers/gpu/drm/omapdrm/omap_plane.c            |   3 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c         |   4 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |   5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |   4 +-
 drivers/gpu/drm/sti/sti_cursor.c                |   1 +
 drivers/gpu/drm/sti/sti_gdp.c                   |   2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c                 |   2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c             |   1 +
 drivers/gpu/drm/tegra/dc.c                      |  12 +--
 drivers/gpu/drm/vc4/vc4_plane.c                 |   2 +-
 drivers/gpu/drm/virtio/virtgpu_plane.c          |   2 +-
 drivers/gpu/drm/zte/zx_plane.c                  |   2 +-
 include/drm/drm_plane.h                         |  21 ++++-
 include/drm/drm_simple_kms_helper.h             |   1 +
 include/uapi/drm/drm.h                          |   1 +
 include/uapi/drm/drm_fourcc.h                   |  11 +++
 include/uapi/drm/drm_mode.h                     |  27 ++++++
 40 files changed, 320 insertions(+), 36 deletions(-)

-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
@ 2017-01-12  0:51 ` Ben Widawsky
  2017-01-12  1:43   ` [Intel-gfx] " Rob Clark
                     ` (2 more replies)
  2017-01-12  0:51 ` [PATCH 2/3] drm/i915: Add format modifiers for Intel Ben Widawsky
                   ` (4 subsequent siblings)
  5 siblings, 3 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12  0:51 UTC (permalink / raw)
  To: Intel GFX, DRI Development; +Cc: Ben Widawsky

Originally based off of a patch by Kristian.

This new ioctl extends DRM_IOCTL_MODE_GETPLANE, by returning information
about the modifiers that will work with each format.

It's modified from Kristian's patch in that the modifiers and formats
are setup by the driver, and then a callback is used to create the
format list. The LOC was enough difference that I don't think it made
sense to leave his authorship, but the new UABI was primarily his idea.

Additionally, I hit a couple of drivers which Kristian missed updating.

It also contains a change requested by Daniel to make the modifiers
array a sentinel based structure instead of a sized one. Upon discussion
on IRC, it was determined that having an invalid modifier might make
sense in general as well.

References: https://patchwork.kernel.org/patch/9482393/
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/arc/arcpgu_crtc.c               |  1 +
 drivers/gpu/drm/arm/hdlcd_crtc.c                |  1 +
 drivers/gpu/drm/arm/malidp_planes.c             |  2 +-
 drivers/gpu/drm/armada/armada_crtc.c            |  1 +
 drivers/gpu/drm/armada/armada_overlay.c         |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |  4 +-
 drivers/gpu/drm/drm_ioctl.c                     |  2 +-
 drivers/gpu/drm/drm_modeset_helper.c            |  1 +
 drivers/gpu/drm/drm_plane.c                     | 67 ++++++++++++++++++++++++-
 drivers/gpu/drm/drm_simple_kms_helper.c         |  3 ++
 drivers/gpu/drm/exynos/exynos_drm_plane.c       |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |  1 +
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c            |  7 ++-
 drivers/gpu/drm/i915/intel_sprite.c             |  4 +-
 drivers/gpu/drm/imx/ipuv3-plane.c               |  4 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c        |  2 +-
 drivers/gpu/drm/meson/meson_plane.c             |  1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |  2 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.c               |  2 +-
 drivers/gpu/drm/nouveau/nv50_display.c          |  5 +-
 drivers/gpu/drm/omapdrm/omap_plane.c            |  3 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +-
 drivers/gpu/drm/sti/sti_cursor.c                |  1 +
 drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c             |  1 +
 drivers/gpu/drm/tegra/dc.c                      | 12 ++---
 drivers/gpu/drm/vc4/vc4_plane.c                 |  2 +-
 drivers/gpu/drm/virtio/virtgpu_plane.c          |  2 +-
 drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
 include/drm/drm_plane.h                         | 21 +++++++-
 include/drm/drm_simple_kms_helper.h             |  1 +
 include/uapi/drm/drm.h                          |  1 +
 include/uapi/drm/drm_fourcc.h                   | 11 ++++
 include/uapi/drm/drm_mode.h                     | 27 ++++++++++
 40 files changed, 182 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
index ad9a95916f1f..cd8a24c7c67d 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -218,6 +218,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 20ebfb4fbdfa..89fded880807 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -283,6 +283,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &hdlcd_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		devm_kfree(drm->dev, plane);
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index eff2fe47e26a..94dbcbc9ad8f 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -283,7 +283,7 @@ int malidp_de_planes_init(struct drm_device *drm)
 					DRM_PLANE_TYPE_OVERLAY;
 		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
 					       &malidp_de_plane_funcs, formats,
-					       n, plane_type, NULL);
+					       n, NULL, plane_type, NULL);
 		if (ret < 0)
 			goto cleanup;
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e62ee4498ce4..39330145ba2a 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1250,6 +1250,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 				       &armada_primary_plane_funcs,
 				       armada_primary_formats,
 				       ARRAY_SIZE(armada_primary_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 34cb73d0db77..6a1ca8aa8e16 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -458,6 +458,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 				       &armada_ovl_plane_funcs,
 				       armada_ovl_formats,
 				       ARRAY_SIZE(armada_ovl_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (ret) {
 		kfree(dplane);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index bd2791c4b002..f12cec0bc58c 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -1038,7 +1038,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, &plane->base, 0,
 				       &layer_plane_funcs,
 				       desc->formats->formats,
-				       desc->formats->nformats, type, NULL);
+				       desc->formats->nformats,
+				       NULL,
+				       type, NULL);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a7c61c23685a..c820d99d9231 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -614,7 +614,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE2, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index 2b33825f2f93..9cb1eede0b4d 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
 				       &drm_primary_helper_funcs,
 				       safe_modeset_formats,
 				       ARRAY_SIZE(safe_modeset_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 7b7275f0c2df..2d4fad5db8ed 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
  * @funcs: callbacks for the new plane
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of struct drm_format modifiers terminated by INVALID
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default name
  *
@@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats, unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...)
 {
 	struct drm_mode_config *config = &dev->mode_config;
+	unsigned int format_modifier_count = 0;
 	int ret;
 
 	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +108,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		return -ENOMEM;
 	}
 
+	if (format_modifiers) {
+		const uint64_t *temp_modifiers = format_modifiers;
+		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
+			format_modifier_count++;
+	}
+
+	if (format_modifier_count)
+		DRM_DEBUG_KMS("%d format modifiers added to list\n",
+			      format_modifier_count);
+
+	plane->modifier_count = format_modifier_count;
+	plane->modifiers = kmalloc_array(format_modifier_count,
+					 sizeof(format_modifiers[0]),
+					 GFP_KERNEL);
+
+	if (format_modifier_count && !plane->modifiers) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		kfree(plane->format_types);
+		drm_mode_object_unregister(dev, &plane->base);
+		return -ENOMEM;
+	}
+
 	if (name) {
 		va_list ap;
 
@@ -117,12 +142,15 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 	}
 	if (!plane->name) {
 		kfree(plane->format_types);
+		kfree(plane->modifiers);
 		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
 	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 	plane->format_count = format_count;
+	memcpy(plane->modifiers, format_modifiers,
+	       format_modifier_count * sizeof(format_modifiers[0]));
 	plane->possible_crtcs = possible_crtcs;
 	plane->type = type;
 
@@ -205,7 +233,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-					formats, format_count, type, NULL);
+					formats, format_count,
+					NULL, type, NULL);
 }
 EXPORT_SYMBOL(drm_plane_init);
 
@@ -224,6 +253,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
 	drm_modeset_lock_fini(&plane->mutex);
 
 	kfree(plane->format_types);
+	kfree(plane->modifiers);
 	drm_mode_object_unregister(dev, &plane->base);
 
 	BUG_ON(list_empty(&plane->head));
@@ -380,12 +410,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
 int drm_mode_getplane(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv)
 {
-	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_get_plane2 *plane_resp = data;
 	struct drm_plane *plane;
 	uint32_t __user *format_ptr;
+	struct drm_format_modifier __user *modifier_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
+	if (plane_resp->flags)
+		return -EINVAL;
 
 	plane = drm_plane_find(dev, plane_resp->plane_id);
 	if (!plane)
@@ -426,6 +459,36 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 	}
 	plane_resp->count_format_types = plane->format_count;
 
+	if (plane->modifier_count &&
+	    plane_resp->count_format_modifiers >= plane->modifier_count) {
+		struct drm_format_modifier mod;
+		int i;
+
+		modifier_ptr = (struct drm_format_modifier __user *)
+			(unsigned long)plane_resp->format_modifier_ptr;
+
+		/* Build the mask for each modifier */
+		for (i = 0; i < plane->modifier_count; i++) {
+			int j;
+			mod.modifier = plane->modifiers[i];
+			for (j = 0; j < plane->format_count; j++) {
+				if (plane->funcs->format_mod_supported &&
+				    plane->funcs->format_mod_supported(plane,
+								       plane->format_types[j],
+								       plane->modifiers[i])) {
+					mod.formats |= 1 << j;
+				}
+			}
+
+			if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
+				return -EFAULT;
+
+			modifier_ptr++;
+		}
+	}
+
+	plane_resp->count_format_modifiers = plane->modifier_count;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 35c5d99296b9..0406e71b38e8 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -193,6 +193,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
  * @funcs: callbacks for the display pipe (optional)
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @modifiers: array of formats modifiers
  * @connector: connector to attach and register (optional)
  *
  * Sets up a display pipeline which consist of a really simple
@@ -213,6 +214,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &pipe->encoder;
@@ -227,6 +229,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0,
 				       &drm_simple_kms_plane_funcs,
 				       formats, format_count,
+				       format_modifiers,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c2f17f30afab..75d4928dd196 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -284,7 +284,7 @@ int exynos_plane_init(struct drm_device *dev,
 				       &exynos_plane_funcs,
 				       config->pixel_formats,
 				       config->num_pixel_formats,
-				       config->type, NULL);
+				       NULL, config->type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index 0a20723aa6e1..9554b245746e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -224,7 +224,7 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 				       &fsl_dcu_drm_plane_funcs,
 				       fsl_dcu_drm_plane_formats,
 				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
 		primary = NULL;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index c655883d3613..919cc807809f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -181,6 +181,7 @@ static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
 	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
 				       channel_formats1,
 				       ARRAY_SIZE(channel_formats1),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY,
 				       NULL);
 	if (ret) {
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index 307d460ab684..b433b8e7c9cd 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -911,7 +911,7 @@ static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane,
 		return ret;
 
 	ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs,
-				       fmts, fmts_cnt, type, NULL);
+				       fmts, fmts_cnt, NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
 		return ret;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b547332eeda1..8715b1083d1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15303,6 +15303,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 					      src_x, src_y, src_w, src_h);
 }
 
+
+
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
 	.update_plane = intel_legacy_cursor_update,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -15387,18 +15389,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
 	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
@@ -15563,7 +15568,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 				       0, &intel_cursor_plane_funcs,
 				       intel_cursor_formats,
 				       ARRAY_SIZE(intel_cursor_formats),
-				       DRM_PLANE_TYPE_CURSOR,
+				       NULL, DRM_PLANE_TYPE_CURSOR,
 				       "cursor %c", pipe_name(pipe));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 063a994815d0..1c2f26d86f76 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1127,13 +1127,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 8b5294d47cee..ef9e11b98b3c 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -496,8 +496,8 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
 
 	ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
 				       &ipu_plane_funcs, ipu_plane_formats,
-				       ARRAY_SIZE(ipu_plane_formats), type,
-				       NULL);
+				       ARRAY_SIZE(ipu_plane_formats),
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("failed to initialize plane\n");
 		kfree(ipu_plane);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index e405e89ed5e5..bec6d14dd070 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -173,7 +173,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	err = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &mtk_plane_funcs, formats,
-				       ARRAY_SIZE(formats), type, NULL);
+				       ARRAY_SIZE(formats), NULL, type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 642b2fab42ff..13c7c2c1d4cc 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -220,6 +220,7 @@ int meson_plane_create(struct meson_drm *priv)
 				 &meson_plane_funcs,
 				 supported_drm_formats,
 				 ARRAY_SIZE(supported_drm_formats),
+				 NULL,
 				 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
 
 	drm_plane_helper_add(plane, &meson_plane_helper_funcs);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 53619d07677e..8f3417e45d4e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -398,7 +398,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
 				 mdp4_plane->formats, mdp4_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 75247ea4335b..c2068c30ca73 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -882,7 +882,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 955441f71500..f29d463e03a4 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -186,7 +186,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	}
 
 	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
-			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, 0,
 			&mxsfb->connector);
 	if (ret < 0) {
 		dev_err(drm->dev, "Cannot setup simple display pipe\n");
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index cb85cb72dc1c..cf5ed98caed4 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1079,8 +1079,9 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
 	wndw->func = func;
 	wndw->dmac = dmac;
 
-	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
-				       nformat, type, "%s-%d", name, index);
+	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw,
+				       format, nformat, NULL,
+				       type, "%s-%d", name, index);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 82b2c23d6769..b4a575cf7e71 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -383,7 +383,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &omap_plane_funcs, omap_plane->formats,
-				       omap_plane->nformats, type, NULL);
+				       omap_plane->nformats,
+				       NULL, type, NULL);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index dcde6288da6c..2b02eccbfb70 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -743,8 +743,8 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
 
 		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
 					       &rcar_du_plane_funcs, formats,
-					       ARRAY_SIZE(formats), type,
-					       NULL);
+					       ARRAY_SIZE(formats),
+					       NULL, type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index b5bfbe50bd87..744be029436b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -364,8 +364,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 					       1 << vsp->index,
 					       &rcar_du_vsp_plane_funcs,
 					       formats_kms,
-					       ARRAY_SIZE(formats_kms), type,
-					       NULL);
+					       ARRAY_SIZE(formats_kms),
+					       NULL,
+					       type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fb5f001f51c3..826b376114f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1221,7 +1221,7 @@ static int vop_create_crtc(struct vop *vop)
 					       0, &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
 				      ret);
@@ -1260,7 +1260,7 @@ static int vop_create_crtc(struct vop *vop)
 					       &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
 				      ret);
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index cca75bddb9ad..f61808b419a5 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -393,6 +393,7 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
 				       &sti_cursor_plane_helpers_funcs,
 				       cursor_supported_formats,
 				       ARRAY_SIZE(cursor_supported_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 877d053d86f4..6bf1a592cee4 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -921,7 +921,7 @@ struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
 				       &sti_gdp_plane_helpers_funcs,
 				       gdp_supported_formats,
 				       ARRAY_SIZE(gdp_supported_formats),
-				       type, NULL);
+				       NULL, type, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		goto err;
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index becf10d255c4..911e8f0f69a6 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1277,7 +1277,7 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
 				       &sti_hqvdp_plane_helpers_funcs,
 				       hqvdp_supported_formats,
 				       ARRAY_SIZE(hqvdp_supported_formats),
-				       DRM_PLANE_TYPE_OVERLAY, NULL);
+				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 5d53c977bca5..827f45364654 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -117,6 +117,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
 				       &sun4i_backend_layer_funcs,
 				       plane->formats, plane->nformats,
+				       NULL,
 				       plane->type, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 7561a95a54e3..9ddea84208c4 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -655,8 +655,8 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
 				       &tegra_primary_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_PRIMARY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -821,8 +821,8 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_cursor_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_CURSOR,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -883,8 +883,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_overlay_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_OVERLAY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 110d1518f5d5..487bb40e0e4e 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -861,7 +861,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0xff,
 				       &vc4_plane_funcs,
 				       formats, num_formats,
-				       type, NULL);
+				       NULL, type, NULL);
 
 	drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 11288ffa4af6..00f368cde0b8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -225,7 +225,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
 	ret = drm_universal_plane_init(dev, plane, 1 << index,
 				       &virtio_gpu_plane_funcs,
 				       formats, nformats,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret)
 		goto err_plane_init;
 
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index b634b090cdc1..c57d4fe5da18 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -287,7 +287,7 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
 
 	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
 				       &zx_plane_funcs, formats, format_count,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
 		return ERR_PTR(ret);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index e049bc52fb07..108a955438e5 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -389,6 +389,20 @@ struct drm_plane_funcs {
 	 */
 	void (*atomic_print_state)(struct drm_printer *p,
 				   const struct drm_plane_state *state);
+
+	/**
+	 * @format_mod_supported:
+	 *
+	 * This optional hook is used for the DRM to determine if the given
+	 * format/modifier combination is valid for the plane. This allows the
+	 * DRM to generate the correct format bitmask (which formats apply to
+	 * which modifier).
+	 *
+	 * True if the given modifier is valid for that format on the plane.
+	 * False otherwise.
+	 */
+	bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,
+				     uint64_t modifier);
 };
 
 /**
@@ -483,6 +497,10 @@ struct drm_plane {
 	unsigned int format_count;
 	bool format_default;
 
+	uint32_t *formats;
+	uint64_t *modifiers;
+	unsigned int modifier_count;
+
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 
@@ -510,13 +528,14 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-extern __printf(8, 9)
+extern __printf(9, 10)
 int drm_universal_plane_init(struct drm_device *dev,
 			     struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats,
 			     unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...);
 extern int drm_plane_init(struct drm_device *dev,
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index fe8c4ba905ac..059cd592a127 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -118,6 +118,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector);
 
 #endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b2c52843bc70..487e0f17113f 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -805,6 +805,7 @@ extern "C" {
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_GETPLANE2	DRM_IOWR(0xB6, struct drm_mode_get_plane2)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 4581e3d41e5c..5859014d93c7 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -162,6 +162,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
 /* add more to the end as needed */
 
+#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
+
 #define fourcc_mod_code(vendor, val) \
 	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
 
@@ -174,6 +176,15 @@ extern "C" {
  */
 
 /*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate list, or to initialize a
+ * variable with an invalid modifier. It might also be used to report an error
+ * back to userspace for certain APIs.
+ */
+#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
+/*
  * Linear Layout
  *
  * Just plain linear layout. Note that this is different from no specifying any
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ce7efe2e8a5e..cea3de3aa301 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -209,6 +209,33 @@ struct drm_mode_get_plane {
 	__u64 format_type_ptr;
 };
 
+struct drm_format_modifier {
+	/* Bitmask of formats in get_plane format list this info
+	 * applies to. */
+	uint64_t formats;
+
+	/* This modifier can be used with the format for this plane. */
+	uint64_t modifier;
+};
+
+struct drm_mode_get_plane2 {
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+	__u64 format_type_ptr;
+
+	/* New in v2 */
+	__u32 count_format_modifiers;
+	__u32 flags;
+	__u64 format_modifier_ptr;
+};
+
 struct drm_mode_get_plane_res {
 	__u64 plane_id_ptr;
 	__u32 count_planes;
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
@ 2017-01-12  0:51 ` Ben Widawsky
  2017-01-12 10:51   ` Ville Syrjälä
  2017-01-12  0:51 ` [PATCH 3/3] drm/i915: Add support for GET_PLANE2 CCS modifiers Ben Widawsky
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12  0:51 UTC (permalink / raw)
  To: Intel GFX, DRI Development; +Cc: Ben Widawsky, Kristian H . Kristensen

This was based on a patch originally by Kristian. It has been modified
pretty heavily to use the new callbacks from the previous patch.

Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
 2 files changed, 137 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8715b1083d1d..26f3a911b999 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
 	DRM_FORMAT_XRGB8888,
 };
 
+static const uint64_t i8xx_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 /* Primary plane formats for gen >= 4 */
 static const uint32_t i965_primary_formats[] = {
 	DRM_FORMAT_C8,
@@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
 	DRM_FORMAT_XBGR2101010,
 };
 
+static const uint64_t i965_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static const uint32_t skl_primary_formats[] = {
 	DRM_FORMAT_C8,
 	DRM_FORMAT_RGB565,
@@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t skl_format_modifiers[] = {
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 /* Cursor formats */
 static const uint32_t intel_cursor_formats[] = {
 	DRM_FORMAT_ARGB8888,
@@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
 	kfree(to_intel_plane(plane));
 }
 
+static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
+{
+	if (modifier == DRM_FORMAT_MOD_NONE)
+		return true;
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XRGB8888:
+		return modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i965_mod_supported(uint32_t format, uint64_t modifier)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+		return modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool skl_mod_supported(uint32_t format, uint64_t modifier)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		return modifier == I915_FORMAT_MOD_Y_TILED ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+		return modifier == I915_FORMAT_MOD_X_TILED;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	default:
+		return false;
+	}
+
+}
+
+static bool intel_plane_format_mod_supported(struct drm_plane *plane,
+					     uint32_t format,
+					     uint64_t modifier)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
+
+	if (modifier == DRM_FORMAT_MOD_NONE)
+		return true;
+
+	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
+		return false;
+
+	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
+		    plane->type != DRM_PLANE_TYPE_OVERLAY))
+	    return false;
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		return skl_mod_supported(format, modifier);
+	else if (INTEL_GEN(dev_priv) >= 4)
+		return i965_mod_supported(format, modifier);
+	else
+		return i8xx_mod_supported(format, modifier);
+
+	return false;
+}
+
 const struct drm_plane_funcs intel_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
 	.atomic_set_property = intel_plane_atomic_set_property,
 	.atomic_duplicate_state = intel_plane_duplicate_state,
 	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = intel_plane_format_mod_supported,
 };
 
 static int
@@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	const uint32_t *intel_primary_formats;
 	unsigned int supported_rotations;
 	unsigned int num_formats;
+	const uint64_t *intel_format_modifiers;
 	int ret;
 
 	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
@@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	if (INTEL_GEN(dev_priv) >= 9) {
 		intel_primary_formats = skl_primary_formats;
 		num_formats = ARRAY_SIZE(skl_primary_formats);
+		intel_format_modifiers = skl_format_modifiers;
 
 		primary->update_plane = skylake_update_primary_plane;
 		primary->disable_plane = skylake_disable_primary_plane;
 	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		intel_primary_formats = i965_primary_formats;
 		num_formats = ARRAY_SIZE(i965_primary_formats);
+		intel_format_modifiers = i965_format_modifiers;
 
 		primary->update_plane = ironlake_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
 	} else if (INTEL_GEN(dev_priv) >= 4) {
 		intel_primary_formats = i965_primary_formats;
 		num_formats = ARRAY_SIZE(i965_primary_formats);
+		intel_format_modifiers = i965_format_modifiers;
 
 		primary->update_plane = i9xx_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
 	} else {
 		intel_primary_formats = i8xx_primary_formats;
 		num_formats = ARRAY_SIZE(i8xx_primary_formats);
+		intel_format_modifiers = i8xx_format_modifiers;
 
 		primary->update_plane = i9xx_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
@@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
 	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 1c2f26d86f76..152ec8196d41 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t ilk_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static const uint32_t snb_plane_formats[] = {
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
@@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t snb_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static const uint32_t vlv_plane_formats[] = {
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_ABGR8888,
@@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t vlv_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static uint32_t skl_plane_formats[] = {
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_ABGR8888,
@@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t skl_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_INVALID
+};
+
 struct intel_plane *
 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, int plane)
@@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 	struct intel_plane_state *state = NULL;
 	unsigned long possible_crtcs;
 	const uint32_t *plane_formats;
+	const uint64_t *modifiers;
 	unsigned int supported_rotations;
 	int num_plane_formats;
 	int ret;
@@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = skl_plane_formats;
 		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
+		modifiers = skl_plane_format_modifiers;
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		intel_plane->can_scale = false;
 		intel_plane->max_downscale = 1;
@@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = vlv_plane_formats;
 		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
+		modifiers = vlv_plane_format_modifiers;
 	} else if (INTEL_GEN(dev_priv) >= 7) {
 		if (IS_IVYBRIDGE(dev_priv)) {
 			intel_plane->can_scale = true;
@@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = snb_plane_formats;
 		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+		modifiers = snb_plane_format_modifiers;
 	} else {
 		intel_plane->can_scale = true;
 		intel_plane->max_downscale = 16;
@@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		if (IS_GEN6(dev_priv)) {
 			plane_formats = snb_plane_formats;
 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+			modifiers = snb_plane_format_modifiers;
 		} else {
 			plane_formats = ilk_plane_formats;
 			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
+			modifiers = ilk_plane_format_modifiers;
 		}
 	}
 
@@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       NULL, DRM_PLANE_TYPE_OVERLAY,
+					       modifiers,
+					       DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       NULL, DRM_PLANE_TYPE_OVERLAY,
+					       modifiers,
+					       DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/3] drm/i915: Add support for GET_PLANE2 CCS modifiers
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
  2017-01-12  0:51 ` [PATCH 2/3] drm/i915: Add format modifiers for Intel Ben Widawsky
@ 2017-01-12  0:51 ` Ben Widawsky
  2017-01-12  1:01 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation Patchwork
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12  0:51 UTC (permalink / raw)
  To: Intel GFX, DRI Development; +Cc: Ben Widawsky

Cc: Kristian Høgsberg <krh@bitplanet.net>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_display.c | 10 ++++++++--
 drivers/gpu/drm/i915/intel_sprite.c  |  2 ++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 26f3a911b999..cf1b19447af1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -97,6 +97,8 @@ static const uint32_t skl_primary_formats[] = {
 };
 
 static const uint64_t skl_format_modifiers[] = {
+	I915_FORMAT_MOD_Yf_TILED_CCS,
+	I915_FORMAT_MOD_Y_TILED_CCS,
 	I915_FORMAT_MOD_Y_TILED,
 	I915_FORMAT_MOD_X_TILED,
 	DRM_FORMAT_MOD_INVALID
@@ -15225,15 +15227,19 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier)
 	switch (format) {
 	case DRM_FORMAT_C8:
 	case DRM_FORMAT_RGB565:
+		return  modifier == I915_FORMAT_MOD_Y_TILED ||
+			modifier == I915_FORMAT_MOD_X_TILED;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_ABGR8888:
-		return modifier == I915_FORMAT_MOD_Y_TILED ||
+		return  modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
+			modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
+			modifier == I915_FORMAT_MOD_Y_TILED ||
 			modifier == I915_FORMAT_MOD_X_TILED;
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_XBGR2101010:
-		return modifier == I915_FORMAT_MOD_X_TILED;
+		return  modifier == I915_FORMAT_MOD_X_TILED;
 	case DRM_FORMAT_YUYV:
 	case DRM_FORMAT_YVYU:
 	case DRM_FORMAT_UYVY:
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 152ec8196d41..eed7195212b7 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1045,6 +1045,8 @@ static uint32_t skl_plane_formats[] = {
 };
 
 static const uint64_t skl_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_Yf_TILED_CCS,
+	I915_FORMAT_MOD_Y_TILED_CCS,
 	I915_FORMAT_MOD_Y_TILED,
 	I915_FORMAT_MOD_X_TILED,
 	DRM_FORMAT_MOD_INVALID
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
                   ` (2 preceding siblings ...)
  2017-01-12  0:51 ` [PATCH 3/3] drm/i915: Add support for GET_PLANE2 CCS modifiers Ben Widawsky
@ 2017-01-12  1:01 ` Patchwork
  2017-01-12  1:23   ` Ben Widawsky
  2017-01-25  6:32 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev2) Patchwork
  2017-01-27  1:02 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev3) Patchwork
  5 siblings, 1 reply; 28+ messages in thread
From: Patchwork @ 2017-01-12  1:01 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx

== Series Details ==

Series: GET_PLANE2 w/ i915 implementation
URL   : https://patchwork.freedesktop.org/series/17873/
State : failure

== Summary ==

  LD [M]  sound/pci/hda/snd-hda-codec-generic.o
  LD      lib/built-in.o
  LD      sound/pci/built-in.o
  LD      drivers/acpi/built-in.o
  LD      drivers/md/dm-mod.o
  LD      sound/built-in.o
  LD      drivers/scsi/scsi_mod.o
  LD      drivers/video/fbdev/core/fb.o
  LD      net/ipv6/ipv6.o
  LD      drivers/video/fbdev/core/built-in.o
  LD      drivers/pci/built-in.o
  LD      drivers/usb/storage/usb-storage.o
  LD      drivers/usb/storage/built-in.o
drivers/gpu/drm/i915/intel_sprite.c:1043:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_sprite.c:1044:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
  LD      net/ipv6/built-in.o
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_sprite.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_sprite.o] Error 1
make[4]: *** Waiting for unfinished jobs....
  LD [M]  drivers/usb/serial/usbserial.o
  LD [M]  drivers/misc/mei/mei-me.o
  LD      drivers/misc/built-in.o
  LD      drivers/thermal/thermal_sys.o
  LD      drivers/thermal/built-in.o
  LD [M]  drivers/gpu/drm/vgem/vgem.o
  LD      drivers/tty/serial/8250/8250.o
  LD [M]  drivers/mmc/core/mmc_block.o
drivers/gpu/drm/i915/intel_display.c:100:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_display.c:101:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
  LD [M]  drivers/net/ethernet/broadcom/genet/genet.o
  LD      drivers/mmc/built-in.o
  LD      drivers/usb/gadget/libcomposite.o
  LD      drivers/video/fbdev/built-in.o
  LD      drivers/spi/built-in.o
drivers/gpu/drm/i915/intel_display.c: In function ‘skl_mod_supported’:
drivers/gpu/drm/i915/intel_display.c:15053:20: error: comparison between pointer and integer [-Werror]
   return  modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
                    ^
drivers/gpu/drm/i915/intel_display.c:15054:13: error: comparison between pointer and integer [-Werror]
    modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
             ^
  LD      drivers/scsi/sd_mod.o
  LD      drivers/scsi/built-in.o
  LD      net/ipv4/built-in.o
  LD [M]  drivers/net/ethernet/intel/igbvf/igbvf.o
  LD      drivers/usb/gadget/udc/udc-core.o
  LD      drivers/usb/gadget/udc/built-in.o
cc1: all warnings being treated as errors
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_display.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_display.o] Error 1
  LD      drivers/usb/gadget/built-in.o
  LD      drivers/video/console/built-in.o
  LD      drivers/video/built-in.o
  LD      drivers/iommu/built-in.o
  LD      drivers/tty/serial/8250/8250_base.o
  LD      drivers/tty/serial/8250/built-in.o
  LD      drivers/tty/serial/built-in.o
  LD      fs/btrfs/btrfs.o
  LD      fs/btrfs/built-in.o
  LD [M]  drivers/net/ethernet/intel/e1000/e1000.o
  LD      drivers/usb/core/usbcore.o
  CC      arch/x86/kernel/cpu/capflags.o
  LD      drivers/gpu/drm/drm.o
  LD      drivers/usb/core/built-in.o
  LD      arch/x86/kernel/cpu/built-in.o
  LD      net/core/built-in.o
  LD      arch/x86/kernel/built-in.o
  LD      net/built-in.o
  LD      drivers/usb/host/xhci-hcd.o
  LD      drivers/tty/vt/built-in.o
  LD      drivers/tty/built-in.o
  LD      arch/x86/built-in.o
  LD [M]  drivers/net/ethernet/intel/igb/igb.o
  LD      drivers/usb/host/built-in.o
  LD      drivers/md/md-mod.o
  LD      drivers/usb/built-in.o
  LD      drivers/md/built-in.o
  LD      fs/ext4/ext4.o
  LD [M]  drivers/net/ethernet/intel/e1000e/e1000e.o
  LD      fs/ext4/built-in.o
  LD      fs/built-in.o
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
make[1]: *** Waiting for unfinished jobs....
  LD      drivers/net/ethernet/built-in.o
  LD      drivers/net/built-in.o
Makefile:988: recipe for target 'drivers' failed
make: *** [drivers] Error 2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation
  2017-01-12  1:01 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation Patchwork
@ 2017-01-12  1:23   ` Ben Widawsky
  0 siblings, 0 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12  1:23 UTC (permalink / raw)
  To: intel-gfx

This is expected because it's based on Ville's patch series to define the new
modifiers.

On 17-01-12 01:01:31, Patchwork wrote:
>== Series Details ==
>
>Series: GET_PLANE2 w/ i915 implementation
>URL   : https://patchwork.freedesktop.org/series/17873/
>State : failure
>
>== Summary ==
>
>  LD [M]  sound/pci/hda/snd-hda-codec-generic.o
>  LD      lib/built-in.o
>  LD      sound/pci/built-in.o
>  LD      drivers/acpi/built-in.o
>  LD      drivers/md/dm-mod.o
>  LD      sound/built-in.o
>  LD      drivers/scsi/scsi_mod.o
>  LD      drivers/video/fbdev/core/fb.o
>  LD      net/ipv6/ipv6.o
>  LD      drivers/video/fbdev/core/built-in.o
>  LD      drivers/pci/built-in.o
>  LD      drivers/usb/storage/usb-storage.o
>  LD      drivers/usb/storage/built-in.o
>drivers/gpu/drm/i915/intel_sprite.c:1043:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
>  I915_FORMAT_MOD_Yf_TILED_CCS,
>  ^
>drivers/gpu/drm/i915/intel_sprite.c:1044:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
>  I915_FORMAT_MOD_Y_TILED_CCS,
>  ^
>  LD      net/ipv6/built-in.o
>scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_sprite.o' failed
>make[4]: *** [drivers/gpu/drm/i915/intel_sprite.o] Error 1
>make[4]: *** Waiting for unfinished jobs....
>  LD [M]  drivers/usb/serial/usbserial.o
>  LD [M]  drivers/misc/mei/mei-me.o
>  LD      drivers/misc/built-in.o
>  LD      drivers/thermal/thermal_sys.o
>  LD      drivers/thermal/built-in.o
>  LD [M]  drivers/gpu/drm/vgem/vgem.o
>  LD      drivers/tty/serial/8250/8250.o
>  LD [M]  drivers/mmc/core/mmc_block.o
>drivers/gpu/drm/i915/intel_display.c:100:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
>  I915_FORMAT_MOD_Yf_TILED_CCS,
>  ^
>drivers/gpu/drm/i915/intel_display.c:101:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
>  I915_FORMAT_MOD_Y_TILED_CCS,
>  ^
>  LD [M]  drivers/net/ethernet/broadcom/genet/genet.o
>  LD      drivers/mmc/built-in.o
>  LD      drivers/usb/gadget/libcomposite.o
>  LD      drivers/video/fbdev/built-in.o
>  LD      drivers/spi/built-in.o
>drivers/gpu/drm/i915/intel_display.c: In function ‘skl_mod_supported’:
>drivers/gpu/drm/i915/intel_display.c:15053:20: error: comparison between pointer and integer [-Werror]
>   return  modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
>                    ^
>drivers/gpu/drm/i915/intel_display.c:15054:13: error: comparison between pointer and integer [-Werror]
>    modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
>             ^
>  LD      drivers/scsi/sd_mod.o
>  LD      drivers/scsi/built-in.o
>  LD      net/ipv4/built-in.o
>  LD [M]  drivers/net/ethernet/intel/igbvf/igbvf.o
>  LD      drivers/usb/gadget/udc/udc-core.o
>  LD      drivers/usb/gadget/udc/built-in.o
>cc1: all warnings being treated as errors
>scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_display.o' failed
>make[4]: *** [drivers/gpu/drm/i915/intel_display.o] Error 1
>  LD      drivers/usb/gadget/built-in.o
>  LD      drivers/video/console/built-in.o
>  LD      drivers/video/built-in.o
>  LD      drivers/iommu/built-in.o
>  LD      drivers/tty/serial/8250/8250_base.o
>  LD      drivers/tty/serial/8250/built-in.o
>  LD      drivers/tty/serial/built-in.o
>  LD      fs/btrfs/btrfs.o
>  LD      fs/btrfs/built-in.o
>  LD [M]  drivers/net/ethernet/intel/e1000/e1000.o
>  LD      drivers/usb/core/usbcore.o
>  CC      arch/x86/kernel/cpu/capflags.o
>  LD      drivers/gpu/drm/drm.o
>  LD      drivers/usb/core/built-in.o
>  LD      arch/x86/kernel/cpu/built-in.o
>  LD      net/core/built-in.o
>  LD      arch/x86/kernel/built-in.o
>  LD      net/built-in.o
>  LD      drivers/usb/host/xhci-hcd.o
>  LD      drivers/tty/vt/built-in.o
>  LD      drivers/tty/built-in.o
>  LD      arch/x86/built-in.o
>  LD [M]  drivers/net/ethernet/intel/igb/igb.o
>  LD      drivers/usb/host/built-in.o
>  LD      drivers/md/md-mod.o
>  LD      drivers/usb/built-in.o
>  LD      drivers/md/built-in.o
>  LD      fs/ext4/ext4.o
>  LD [M]  drivers/net/ethernet/intel/e1000e/e1000e.o
>  LD      fs/ext4/built-in.o
>  LD      fs/built-in.o
>scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm/i915' failed
>make[3]: *** [drivers/gpu/drm/i915] Error 2
>scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm' failed
>make[2]: *** [drivers/gpu/drm] Error 2
>scripts/Makefile.build:551: recipe for target 'drivers/gpu' failed
>make[1]: *** [drivers/gpu] Error 2
>make[1]: *** Waiting for unfinished jobs....
>  LD      drivers/net/ethernet/built-in.o
>  LD      drivers/net/built-in.o
>Makefile:988: recipe for target 'drivers' failed
>make: *** [drivers] Error 2
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
@ 2017-01-12  1:43   ` Rob Clark
  2017-01-12  9:38     ` Ville Syrjälä
  2017-01-12 10:23   ` [Intel-gfx] " Ville Syrjälä
  2017-01-25  5:20   ` [PATCH 1/3] [v2] " Ben Widawsky
  2 siblings, 1 reply; 28+ messages in thread
From: Rob Clark @ 2017-01-12  1:43 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, DRI Development

On Wed, Jan 11, 2017 at 7:51 PM, Ben Widawsky <ben@bwidawsk.net> wrote:
>
> +struct drm_format_modifier {
> +       /* Bitmask of formats in get_plane format list this info
> +        * applies to. */
> +       uint64_t formats;

re: the uabi, I'd suggest to at least make this 'u32 offset; u32
formats'.. we can keep the existing implementation in this patch and
always set 'offset' to zero, and let the first one to hit more than 32
formats deal with the implementation.  (Maybe a strategically placed
WARN_ON() if you go that route..)

Otherwise I guess it is just a couple years until getplane3 ;-)

BR,
-R

> +
> +       /* This modifier can be used with the format for this plane. */
> +       uint64_t modifier;
> +};
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  1:43   ` [Intel-gfx] " Rob Clark
@ 2017-01-12  9:38     ` Ville Syrjälä
  2017-01-12 14:56       ` Rob Clark
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12  9:38 UTC (permalink / raw)
  To: Rob Clark; +Cc: Ben Widawsky, Intel GFX, DRI Development

On Wed, Jan 11, 2017 at 08:43:16PM -0500, Rob Clark wrote:
> On Wed, Jan 11, 2017 at 7:51 PM, Ben Widawsky <ben@bwidawsk.net> wrote:
> >
> > +struct drm_format_modifier {
> > +       /* Bitmask of formats in get_plane format list this info
> > +        * applies to. */
> > +       uint64_t formats;
> 
> re: the uabi, I'd suggest to at least make this 'u32 offset; u32
> formats'.. we can keep the existing implementation in this patch and
> always set 'offset' to zero, and let the first one to hit more than 32
> formats deal with the implementation.  (Maybe a strategically placed
> WARN_ON() if you go that route..)

Isn't an implicit offset enough? As in first mask for a specific
modifier is for format indexes 0-63, second mask for the same modifier
is for 64-127, and so on.

The bigger issue is the userspace side I think. If we don't add the
userspace side code to handle this case from the get go, it's going to
be hard to actually start doing it from the kernel side.

> 
> Otherwise I guess it is just a couple years until getplane3 ;-)
> 
> BR,
> -R
> 
> > +
> > +       /* This modifier can be used with the format for this plane. */
> > +       uint64_t modifier;
> > +};
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
  2017-01-12  1:43   ` [Intel-gfx] " Rob Clark
@ 2017-01-12 10:23   ` Ville Syrjälä
  2023-11-24 15:08     ` Andy Shevchenko
  2017-01-25  5:20   ` [PATCH 1/3] [v2] " Ben Widawsky
  2 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12 10:23 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, DRI Development

On Wed, Jan 11, 2017 at 04:51:16PM -0800, Ben Widawsky wrote:
> Originally based off of a patch by Kristian.
> 
> This new ioctl extends DRM_IOCTL_MODE_GETPLANE, by returning information
> about the modifiers that will work with each format.
> 
> It's modified from Kristian's patch in that the modifiers and formats
> are setup by the driver, and then a callback is used to create the
> format list. The LOC was enough difference that I don't think it made
> sense to leave his authorship, but the new UABI was primarily his idea.
> 
> Additionally, I hit a couple of drivers which Kristian missed updating.
> 
> It also contains a change requested by Daniel to make the modifiers
> array a sentinel based structure instead of a sized one. Upon discussion
> on IRC, it was determined that having an invalid modifier might make
> sense in general as well.
> 
> References: https://patchwork.kernel.org/patch/9482393/
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
<snip>
> diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
> index 2b33825f2f93..9cb1eede0b4d 100644
> --- a/drivers/gpu/drm/drm_modeset_helper.c
> +++ b/drivers/gpu/drm/drm_modeset_helper.c
> @@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
>  				       &drm_primary_helper_funcs,
>  				       safe_modeset_formats,
>  				       ARRAY_SIZE(safe_modeset_formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		kfree(primary);
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index 7b7275f0c2df..2d4fad5db8ed 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
>   * @funcs: callbacks for the new plane
>   * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
> + * @format_modifiers: array of struct drm_format modifiers terminated by INVALID
>   * @type: type of plane (overlay, primary, cursor)
>   * @name: printf style format string for the plane name, or NULL for default name
>   *
> @@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  			     uint32_t possible_crtcs,
>  			     const struct drm_plane_funcs *funcs,
>  			     const uint32_t *formats, unsigned int format_count,
> +			     const uint64_t *format_modifiers,
>  			     enum drm_plane_type type,
>  			     const char *name, ...)
>  {
>  	struct drm_mode_config *config = &dev->mode_config;
> +	unsigned int format_modifier_count = 0;
>  	int ret;
>  
>  	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
> @@ -105,6 +108,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  		return -ENOMEM;
>  	}
>  
> +	if (format_modifiers) {
> +		const uint64_t *temp_modifiers = format_modifiers;
> +		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
> +			format_modifier_count++;
> +	}
> +
> +	if (format_modifier_count)
> +		DRM_DEBUG_KMS("%d format modifiers added to list\n",
> +			      format_modifier_count);

nit: Not sure this is printk worthy.

> +
> +	plane->modifier_count = format_modifier_count;
> +	plane->modifiers = kmalloc_array(format_modifier_count,
> +					 sizeof(format_modifiers[0]),
> +					 GFP_KERNEL);
> +
> +	if (format_modifier_count && !plane->modifiers) {
> +		DRM_DEBUG_KMS("out of memory when allocating plane\n");
> +		kfree(plane->format_types);
> +		drm_mode_object_unregister(dev, &plane->base);
> +		return -ENOMEM;
> +	}
> +
>  	if (name) {
>  		va_list ap;
>  
> @@ -117,12 +142,15 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  	}
>  	if (!plane->name) {
>  		kfree(plane->format_types);
> +		kfree(plane->modifiers);
>  		drm_mode_object_unregister(dev, &plane->base);
>  		return -ENOMEM;
>  	}
>  
>  	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
>  	plane->format_count = format_count;
> +	memcpy(plane->modifiers, format_modifiers,
> +	       format_modifier_count * sizeof(format_modifiers[0]));

Looks all right since we do the same for formats anyway. But it did
occur to me (twice at least) that a kmemdup_array() might a nice thing
to have for things like this. But that's a separate topic.

>  	plane->possible_crtcs = possible_crtcs;
>  	plane->type = type;
>  
> @@ -205,7 +233,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  
>  	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
>  	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
> -					formats, format_count, type, NULL);
> +					formats, format_count,
> +					NULL, type, NULL);
>  }
>  EXPORT_SYMBOL(drm_plane_init);
>  
> @@ -224,6 +253,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
>  	drm_modeset_lock_fini(&plane->mutex);
>  
>  	kfree(plane->format_types);
> +	kfree(plane->modifiers);
>  	drm_mode_object_unregister(dev, &plane->base);
>  
>  	BUG_ON(list_empty(&plane->head));
> @@ -380,12 +410,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
>  int drm_mode_getplane(struct drm_device *dev, void *data,
>  		      struct drm_file *file_priv)
>  {
> -	struct drm_mode_get_plane *plane_resp = data;
> +	struct drm_mode_get_plane2 *plane_resp = data;
>  	struct drm_plane *plane;
>  	uint32_t __user *format_ptr;
> +	struct drm_format_modifier __user *modifier_ptr;
>  
>  	if (!drm_core_check_feature(dev, DRIVER_MODESET))
>  		return -EINVAL;
> +	if (plane_resp->flags)
> +		return -EINVAL;
>  
>  	plane = drm_plane_find(dev, plane_resp->plane_id);
>  	if (!plane)
> @@ -426,6 +459,36 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
>  	}
>  	plane_resp->count_format_types = plane->format_count;
>  
> +	if (plane->modifier_count &&
> +	    plane_resp->count_format_modifiers >= plane->modifier_count) {
> +		struct drm_format_modifier mod;
> +		int i;
> +
> +		modifier_ptr = (struct drm_format_modifier __user *)
> +			(unsigned long)plane_resp->format_modifier_ptr;

Didn't we have some something_user_ptr() thing? Hmm, I guess it's in i915 only.

> +
> +		/* Build the mask for each modifier */
> +		for (i = 0; i < plane->modifier_count; i++) {
> +			int j;
> +			mod.modifier = plane->modifiers[i];
> +			for (j = 0; j < plane->format_count; j++) {

If we don't want to try and deal with more than 64 formats, I think we
need to make drm_universal_plane_init() WARN+bail if the driver
passes in more than that.

> +				if (plane->funcs->format_mod_supported &&
> +				    plane->funcs->format_mod_supported(plane,
> +								       plane->format_types[j],
> +								       plane->modifiers[i])) {
> +					mod.formats |= 1 << j;
> +				}
> +			}
> +
> +			if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
> +				return -EFAULT;
> +
> +			modifier_ptr++;
> +		}
> +	}
> +
> +	plane_resp->count_format_modifiers = plane->modifier_count;
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 35c5d99296b9..0406e71b38e8 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -193,6 +193,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>   * @funcs: callbacks for the display pipe (optional)
>   * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
> + * @modifiers: array of formats modifiers

@format_modifiers

>   * @connector: connector to attach and register (optional)
>   *
>   * Sets up a display pipeline which consist of a really simple
> @@ -213,6 +214,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
>  			struct drm_simple_display_pipe *pipe,
>  			const struct drm_simple_display_pipe_funcs *funcs,
>  			const uint32_t *formats, unsigned int format_count,
> +			const uint64_t *format_modifiers,
>  			struct drm_connector *connector)
>  {
>  	struct drm_encoder *encoder = &pipe->encoder;
> @@ -227,6 +229,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
>  	ret = drm_universal_plane_init(dev, plane, 0,
>  				       &drm_simple_kms_plane_funcs,
>  				       formats, format_count,
> +				       format_modifiers,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret)
>  		return ret;
<snip>
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index ce7efe2e8a5e..cea3de3aa301 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -209,6 +209,33 @@ struct drm_mode_get_plane {
>  	__u64 format_type_ptr;
>  };
>  
> +struct drm_format_modifier {
> +	/* Bitmask of formats in get_plane format list this info
> +	 * applies to. */
> +	uint64_t formats;
> +
> +	/* This modifier can be used with the format for this plane. */
> +	uint64_t modifier;
> +};
> +
> +struct drm_mode_get_plane2 {
> +	__u32 plane_id;
> +
> +	__u32 crtc_id;
> +	__u32 fb_id;
> +
> +	__u32 possible_crtcs;
> +	__u32 gamma_size;
> +
> +	__u32 count_format_types;
> +	__u64 format_type_ptr;
> +
> +	/* New in v2 */
> +	__u32 count_format_modifiers;
> +	__u32 flags;

ocd induced idea: Maybe put flags before the count?

> +	__u64 format_modifier_ptr;
> +};
> +
>  struct drm_mode_get_plane_res {
>  	__u64 plane_id_ptr;
>  	__u32 count_planes;

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12  0:51 ` [PATCH 2/3] drm/i915: Add format modifiers for Intel Ben Widawsky
@ 2017-01-12 10:51   ` Ville Syrjälä
  2017-01-12 18:00     ` Ben Widawsky
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12 10:51 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Kristian H . Kristensen, DRI Development

On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
> This was based on a patch originally by Kristian. It has been modified
> pretty heavily to use the new callbacks from the previous patch.
> 
> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
>  2 files changed, 137 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 8715b1083d1d..26f3a911b999 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
>  	DRM_FORMAT_XRGB8888,
>  };
>  
> +static const uint64_t i8xx_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,

Did we want to list the linear modifier in these as well?

> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  /* Primary plane formats for gen >= 4 */
>  static const uint32_t i965_primary_formats[] = {
>  	DRM_FORMAT_C8,
> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
>  	DRM_FORMAT_XBGR2101010,
>  };
>  
> +static const uint64_t i965_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};

We could just share the i8xx array. The name of the array should perhaps
be i9xx_format_modifiers[] in that case. That's sort of the naming
convention we've been left with for things that apply to more or less
all the platforms.

> +
>  static const uint32_t skl_primary_formats[] = {
>  	DRM_FORMAT_C8,
>  	DRM_FORMAT_RGB565,
> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t skl_format_modifiers[] = {
> +	I915_FORMAT_MOD_Y_TILED,

Yf missing? and linear

> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  /* Cursor formats */
>  static const uint32_t intel_cursor_formats[] = {
>  	DRM_FORMAT_ARGB8888,
> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
>  	kfree(to_intel_plane(plane));
>  }
>  
> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	if (modifier == DRM_FORMAT_MOD_NONE)
> +		return true;
> +
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB1555:
> +	case DRM_FORMAT_XRGB8888:
> +		return modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_XBGR2101010:
> +		return modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}

Hmm. There should be no format vs. tiling restrictions on these
platforms, so presumably a simple "return true" should cover it all.
That does perhaps remove the usefulness of these functions for
verifying that the format or modifier is supported at all, but I've been
thinking that addfb should perhaps just iterate through the format and
modifier lists for every plane. Would avoid having to effectively 
maintain the same lists in multiple places.

> +
> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_ARGB8888:
> +	case DRM_FORMAT_ABGR8888:
> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
> +			modifier == I915_FORMAT_MOD_X_TILED;
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_XBGR2101010:
> +		return modifier == I915_FORMAT_MOD_X_TILED;
> +	case DRM_FORMAT_YUYV:
> +	case DRM_FORMAT_YVYU:
> +	case DRM_FORMAT_UYVY:
> +	case DRM_FORMAT_VYUY:

IIRC on SKL the only restrictions should be that CCS modifiers are
limited to 8:8:8:8 formats only. Other modifiers should work
with any format.

> +	default:
> +		return false;
> +	}
> +
> +}
> +
> +static bool intel_plane_format_mod_supported(struct drm_plane *plane,
> +					     uint32_t format,
> +					     uint64_t modifier)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
> +
> +	if (modifier == DRM_FORMAT_MOD_NONE)
> +		return true;
> +
> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> +		return false;
> +
> +	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
> +		    plane->type != DRM_PLANE_TYPE_OVERLAY))
> +	    return false;
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		return skl_mod_supported(format, modifier);
> +	else if (INTEL_GEN(dev_priv) >= 4)
> +		return i965_mod_supported(format, modifier);
> +	else
> +		return i8xx_mod_supported(format, modifier);
> +
> +	return false;
> +}
> +
>  const struct drm_plane_funcs intel_plane_funcs = {
>  	.update_plane = drm_atomic_helper_update_plane,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
>  	.atomic_set_property = intel_plane_atomic_set_property,
>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>  	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = intel_plane_format_mod_supported,
>  };
>  
>  static int
> @@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	const uint32_t *intel_primary_formats;
>  	unsigned int supported_rotations;
>  	unsigned int num_formats;
> +	const uint64_t *intel_format_modifiers;
>  	int ret;
>  
>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> @@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	if (INTEL_GEN(dev_priv) >= 9) {
>  		intel_primary_formats = skl_primary_formats;
>  		num_formats = ARRAY_SIZE(skl_primary_formats);
> +		intel_format_modifiers = skl_format_modifiers;
>  
>  		primary->update_plane = skylake_update_primary_plane;
>  		primary->disable_plane = skylake_disable_primary_plane;
>  	} else if (HAS_PCH_SPLIT(dev_priv)) {
>  		intel_primary_formats = i965_primary_formats;
>  		num_formats = ARRAY_SIZE(i965_primary_formats);
> +		intel_format_modifiers = i965_format_modifiers;
>  
>  		primary->update_plane = ironlake_update_primary_plane;
>  		primary->disable_plane = i9xx_disable_primary_plane;
>  	} else if (INTEL_GEN(dev_priv) >= 4) {
>  		intel_primary_formats = i965_primary_formats;
>  		num_formats = ARRAY_SIZE(i965_primary_formats);
> +		intel_format_modifiers = i965_format_modifiers;
>  
>  		primary->update_plane = i9xx_update_primary_plane;
>  		primary->disable_plane = i9xx_disable_primary_plane;
>  	} else {
>  		intel_primary_formats = i8xx_primary_formats;
>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
> +		intel_format_modifiers = i8xx_format_modifiers;
>  
>  		primary->update_plane = i9xx_update_primary_plane;
>  		primary->disable_plane = i9xx_disable_primary_plane;
> @@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane 1%c", pipe_name(pipe));
>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "primary %c", pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane %c", plane_name(primary->plane));
>  	if (ret)
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 1c2f26d86f76..152ec8196d41 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t ilk_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static const uint32_t snb_plane_formats[] = {
>  	DRM_FORMAT_XBGR8888,
>  	DRM_FORMAT_XRGB8888,
> @@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t snb_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static const uint32_t vlv_plane_formats[] = {
>  	DRM_FORMAT_RGB565,
>  	DRM_FORMAT_ABGR8888,
> @@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t vlv_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static uint32_t skl_plane_formats[] = {
>  	DRM_FORMAT_RGB565,
>  	DRM_FORMAT_ABGR8888,
> @@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t skl_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_Y_TILED,
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  struct intel_plane *
>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  			  enum pipe pipe, int plane)
> @@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  	struct intel_plane_state *state = NULL;
>  	unsigned long possible_crtcs;
>  	const uint32_t *plane_formats;
> +	const uint64_t *modifiers;
>  	unsigned int supported_rotations;
>  	int num_plane_formats;
>  	int ret;
> @@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = skl_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
> +		modifiers = skl_plane_format_modifiers;
>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>  		intel_plane->can_scale = false;
>  		intel_plane->max_downscale = 1;
> @@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = vlv_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
> +		modifiers = vlv_plane_format_modifiers;
>  	} else if (INTEL_GEN(dev_priv) >= 7) {
>  		if (IS_IVYBRIDGE(dev_priv)) {
>  			intel_plane->can_scale = true;
> @@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = snb_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> +		modifiers = snb_plane_format_modifiers;
>  	} else {
>  		intel_plane->can_scale = true;
>  		intel_plane->max_downscale = 16;
> @@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  		if (IS_GEN6(dev_priv)) {
>  			plane_formats = snb_plane_formats;
>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> +			modifiers = snb_plane_format_modifiers;
>  		} else {
>  			plane_formats = ilk_plane_formats;
>  			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
> +			modifiers = ilk_plane_format_modifiers;
>  		}
>  	}
>  
> @@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>  					       possible_crtcs, &intel_plane_funcs,
>  					       plane_formats, num_plane_formats,
> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> +					       modifiers,
> +					       DRM_PLANE_TYPE_OVERLAY,
>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>  					       possible_crtcs, &intel_plane_funcs,
>  					       plane_formats, num_plane_formats,
> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> +					       modifiers,
> +					       DRM_PLANE_TYPE_OVERLAY,
>  					       "sprite %c", sprite_name(pipe, plane));
>  	if (ret)
>  		goto fail;
> -- 
> 2.11.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  9:38     ` Ville Syrjälä
@ 2017-01-12 14:56       ` Rob Clark
  2017-01-12 17:04         ` Daniel Stone
  0 siblings, 1 reply; 28+ messages in thread
From: Rob Clark @ 2017-01-12 14:56 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ben Widawsky, Intel GFX, DRI Development

On Thu, Jan 12, 2017 at 4:38 AM, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> On Wed, Jan 11, 2017 at 08:43:16PM -0500, Rob Clark wrote:
>> On Wed, Jan 11, 2017 at 7:51 PM, Ben Widawsky <ben@bwidawsk.net> wrote:
>> >
>> > +struct drm_format_modifier {
>> > +       /* Bitmask of formats in get_plane format list this info
>> > +        * applies to. */
>> > +       uint64_t formats;
>>
>> re: the uabi, I'd suggest to at least make this 'u32 offset; u32
>> formats'.. we can keep the existing implementation in this patch and
>> always set 'offset' to zero, and let the first one to hit more than 32
>> formats deal with the implementation.  (Maybe a strategically placed
>> WARN_ON() if you go that route..)
>
> Isn't an implicit offset enough? As in first mask for a specific
> modifier is for format indexes 0-63, second mask for the same modifier
> is for 64-127, and so on.

hmm, hadn't thought of that approach.  Definitely if we go w/ implicit
then we want to have userspace support from the get-go.  For explicit,
I guess userspace could complain and ignore if it saw a non-zero
offset similar to what we do w/ pad and unknown flags in the other
direction?

Not sure if that would fly or not..  I guess it is not a *critical*
fail, it just means userspace won't realize that some modifiers are
supported on some formats.. otoh the implicit approach could confuse a
userspace that didn't realize the offset into thinking modifiers
*were* supported on formats where they are not.. that seems like a
bigger problem.

BR,
-R

> The bigger issue is the userspace side I think. If we don't add the
> userspace side code to handle this case from the get go, it's going to
> be hard to actually start doing it from the kernel side.
>
>>
>> Otherwise I guess it is just a couple years until getplane3 ;-)
>>
>> BR,
>> -R
>>
>> > +
>> > +       /* This modifier can be used with the format for this plane. */
>> > +       uint64_t modifier;
>> > +};
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 14:56       ` Rob Clark
@ 2017-01-12 17:04         ` Daniel Stone
  2017-01-12 17:45           ` Ville Syrjälä
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Stone @ 2017-01-12 17:04 UTC (permalink / raw)
  To: Rob Clark; +Cc: DRI Development, Ben Widawsky, Intel GFX

Hi,

On 12 January 2017 at 14:56, Rob Clark <robdclark@gmail.com> wrote:
> On Thu, Jan 12, 2017 at 4:38 AM, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
>> Isn't an implicit offset enough? As in first mask for a specific
>> modifier is for format indexes 0-63, second mask for the same modifier
>> is for 64-127, and so on.
>
> hmm, hadn't thought of that approach.  Definitely if we go w/ implicit
> then we want to have userspace support from the get-go.  For explicit,
> I guess userspace could complain and ignore if it saw a non-zero
> offset similar to what we do w/ pad and unknown flags in the other
> direction?

Implicit is clever but horrible. AFAICT, the only way to do it
properly would be to have a nested forwards loop walk when you first
hit a modifier, searching for further occurrences of that modifier to
collect the complete set of formats that modifier applies to.
Depending on what you did with the structures, you'd either have to
destroy the drm_format_modifiers in the GetPlane return so further
instances of your outer loop didn't hit them, or have a _second_
nested loop walk into wherever you copied the formats/modifiers,
searching for anything with that.

Too clever by half, and everyone will get it wrong. Just add an explicit offset.

Cheers,
Daniel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 17:04         ` Daniel Stone
@ 2017-01-12 17:45           ` Ville Syrjälä
  2017-01-12 17:50             ` Daniel Stone
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12 17:45 UTC (permalink / raw)
  To: Daniel Stone; +Cc: Intel GFX, Ben Widawsky, DRI Development

On Thu, Jan 12, 2017 at 05:04:46PM +0000, Daniel Stone wrote:
> Hi,
> 
> On 12 January 2017 at 14:56, Rob Clark <robdclark@gmail.com> wrote:
> > On Thu, Jan 12, 2017 at 4:38 AM, Ville Syrjälä
> > <ville.syrjala@linux.intel.com> wrote:
> >> Isn't an implicit offset enough? As in first mask for a specific
> >> modifier is for format indexes 0-63, second mask for the same modifier
> >> is for 64-127, and so on.
> >
> > hmm, hadn't thought of that approach.  Definitely if we go w/ implicit
> > then we want to have userspace support from the get-go.  For explicit,
> > I guess userspace could complain and ignore if it saw a non-zero
> > offset similar to what we do w/ pad and unknown flags in the other
> > direction?
> 
> Implicit is clever but horrible. AFAICT, the only way to do it
> properly would be to have a nested forwards loop walk when you first
> hit a modifier, searching for further occurrences of that modifier to
> collect the complete set of formats that modifier applies to.

Not sure for what that is the "only way". In fact I can't right now
think of any operation that would require an extra loop necessarily.
For some things you might just want to look for a specific
format+modifier combo, for that it doesn't matter how many blocks there
are. And if you want to transform the reply into some less convoluted
form, well then you'd just need some modifier+dynamic format list thing,
or if you want to keep to bitmasks you'd either need a bitmask that can
grow when running out of bits or just make it big enough to handle a
sufficiently large worst case number of bits.

Dunno, maybe I just lack imagination. Then again, I'm not even sure if
we're talking about userspace of kernel code here, which might explain
my general confusion :)

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 17:45           ` Ville Syrjälä
@ 2017-01-12 17:50             ` Daniel Stone
  2017-01-12 18:11               ` Ville Syrjälä
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Stone @ 2017-01-12 17:50 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel GFX, Ben Widawsky, DRI Development

Hi,

On 12 January 2017 at 17:45, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> On Thu, Jan 12, 2017 at 05:04:46PM +0000, Daniel Stone wrote:
>> Implicit is clever but horrible. AFAICT, the only way to do it
>> properly would be to have a nested forwards loop walk when you first
>> hit a modifier, searching for further occurrences of that modifier to
>> collect the complete set of formats that modifier applies to.
>
> Not sure for what that is the "only way". In fact I can't right now
> think of any operation that would require an extra loop necessarily.
> For some things you might just want to look for a specific
> format+modifier combo, for that it doesn't matter how many blocks there
> are.

Right, that just needs a local variable to act as a counter.

> And if you want to transform the reply into some less convoluted
> form, well then you'd just need some modifier+dynamic format list thing,
> or if you want to keep to bitmasks you'd either need a bitmask that can
> grow when running out of bits or just make it big enough to handle a
> sufficiently large worst case number of bits.
>
> Dunno, maybe I just lack imagination. Then again, I'm not even sure if
> we're talking about userspace of kernel code here, which might explain
> my general confusion :)

I'm talking about userspace, where I want to have:
struct drm_plane {
    struct {
        uint32_t format;
        uint64_t modifiers[];
    } formats[];
}

Rather than keeping the original format around and doing the lookup every time.

Cheers,
Daniel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12 10:51   ` Ville Syrjälä
@ 2017-01-12 18:00     ` Ben Widawsky
  2017-01-12 18:32       ` Ville Syrjälä
  0 siblings, 1 reply; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12 18:00 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: Intel GFX, Kristian H . Kristensen, DRI Development

On 17-01-12 12:51:20, Ville Syrjälä wrote:
>On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
>> This was based on a patch originally by Kristian. It has been modified
>> pretty heavily to use the new callbacks from the previous patch.
>>
>> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
>> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
>>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
>>  2 files changed, 137 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 8715b1083d1d..26f3a911b999 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
>>  	DRM_FORMAT_XRGB8888,
>>  };
>>
>> +static const uint64_t i8xx_format_modifiers[] = {
>> +	I915_FORMAT_MOD_X_TILED,
>
>Did we want to list the linear modifier in these as well?
>

Yeah. My initial response was no, but yes. We should. I was using
DRM_FORMAT_MOD_NONE in its place, it should be linear, and it should be defined
in the array.

>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  /* Primary plane formats for gen >= 4 */
>>  static const uint32_t i965_primary_formats[] = {
>>  	DRM_FORMAT_C8,
>> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
>>  	DRM_FORMAT_XBGR2101010,
>>  };
>>
>> +static const uint64_t i965_format_modifiers[] = {
>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>
>We could just share the i8xx array. The name of the array should perhaps
>be i9xx_format_modifiers[] in that case. That's sort of the naming
>convention we've been left with for things that apply to more or less
>all the platforms.
>

Got it thanks. This is a relic from Kristian's original patch which tied the
modifiers to the formats in place. It made more sense there to have a separate
i8xx

>> +
>>  static const uint32_t skl_primary_formats[] = {
>>  	DRM_FORMAT_C8,
>>  	DRM_FORMAT_RGB565,
>> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
>>  	DRM_FORMAT_VYUY,
>>  };
>>
>> +static const uint64_t skl_format_modifiers[] = {
>> +	I915_FORMAT_MOD_Y_TILED,
>
>Yf missing? and linear
>

Yes, thanks. I'm kind of scared to add Yf to be honest :P

>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  /* Cursor formats */
>>  static const uint32_t intel_cursor_formats[] = {
>>  	DRM_FORMAT_ARGB8888,
>> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
>>  	kfree(to_intel_plane(plane));
>>  }
>>
>> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
>> +{
>> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> +		return true;
>> +
>> +	switch (format) {
>> +	case DRM_FORMAT_C8:
>> +	case DRM_FORMAT_RGB565:
>> +	case DRM_FORMAT_XRGB1555:
>> +	case DRM_FORMAT_XRGB8888:
>> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
>> +{
>> +	switch (format) {
>> +	case DRM_FORMAT_C8:
>> +	case DRM_FORMAT_RGB565:
>> +	case DRM_FORMAT_XRGB8888:
>> +	case DRM_FORMAT_XBGR8888:
>> +	case DRM_FORMAT_XRGB2101010:
>> +	case DRM_FORMAT_XBGR2101010:
>> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> +	default:
>> +		return false;
>> +	}
>> +}
>
>Hmm. There should be no format vs. tiling restrictions on these
>platforms, so presumably a simple "return true" should cover it all.
>That does perhaps remove the usefulness of these functions for
>verifying that the format or modifier is supported at all

One of the reasons for changing to this current format-modifier lookup at all
was Kristian's approach was considered fragile. If for whatever reason formats
are added, or removed, we'll catch it here. Also, it maybe let's us do something
on cursor plane at some point (I don't actually know). So yeah, we can return
true, but I like that it's spelled out explicitly. Makes it easy to compare it
to the docs as well to make sure our code is correct.

The benefit is of course I can combine i965_mod_supported() with
i8xx_mod_supported()

I'm honestly fine with changing it as well, I just don't see a huge reason to
change it since I've already typed it up. I'll leave it to you.

[ ] Yes, change it.
[ ] No, leave it.

>but I've been thinking that addfb should perhaps just iterate through the
>format and modifier lists for every plane. Would avoid having to effectively
>maintain the same lists in multiple places.
>

I don't quite follow this. Can you elaborate?

>> +
>> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
>> +{
>> +	switch (format) {
>> +	case DRM_FORMAT_C8:
>> +	case DRM_FORMAT_RGB565:
>> +	case DRM_FORMAT_XRGB8888:
>> +	case DRM_FORMAT_XBGR8888:
>> +	case DRM_FORMAT_ARGB8888:
>> +	case DRM_FORMAT_ABGR8888:
>> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
>> +			modifier == I915_FORMAT_MOD_X_TILED;
>> +	case DRM_FORMAT_XRGB2101010:
>> +	case DRM_FORMAT_XBGR2101010:
>> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> +	case DRM_FORMAT_YUYV:
>> +	case DRM_FORMAT_YVYU:
>> +	case DRM_FORMAT_UYVY:
>> +	case DRM_FORMAT_VYUY:
>
>IIRC on SKL the only restrictions should be that CCS modifiers are
>limited to 8:8:8:8 formats only. Other modifiers should work
>with any format.
>

This restriction was copied from Kristian's patch. I just checked the docs and
you are correct. So this needs Yf modifier too. (Aside from CCS, rotation is the
one case: x-tiled 1010102 isn't supported).

>> +	default:
>> +		return false;
>> +	}
>> +
>> +}
>> +
>> +static bool intel_plane_format_mod_supported(struct drm_plane *plane,
>> +					     uint32_t format,
>> +					     uint64_t modifier)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
>> +
>> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> +		return true;
>> +
>> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
>> +		return false;
>> +
>> +	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
>> +		    plane->type != DRM_PLANE_TYPE_OVERLAY))
>> +	    return false;
>> +
>> +	if (INTEL_GEN(dev_priv) >= 9)
>> +		return skl_mod_supported(format, modifier);
>> +	else if (INTEL_GEN(dev_priv) >= 4)
>> +		return i965_mod_supported(format, modifier);
>> +	else
>> +		return i8xx_mod_supported(format, modifier);
>> +
>> +	return false;
>> +}
>> +
>>  const struct drm_plane_funcs intel_plane_funcs = {
>>  	.update_plane = drm_atomic_helper_update_plane,
>>  	.disable_plane = drm_atomic_helper_disable_plane,
>> @@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
>>  	.atomic_set_property = intel_plane_atomic_set_property,
>>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>>  	.atomic_destroy_state = intel_plane_destroy_state,
>> +	.format_mod_supported = intel_plane_format_mod_supported,
>>  };
>>
>>  static int
>> @@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>>  	const uint32_t *intel_primary_formats;
>>  	unsigned int supported_rotations;
>>  	unsigned int num_formats;
>> +	const uint64_t *intel_format_modifiers;
>>  	int ret;
>>
>>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
>> @@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>>  	if (INTEL_GEN(dev_priv) >= 9) {
>>  		intel_primary_formats = skl_primary_formats;
>>  		num_formats = ARRAY_SIZE(skl_primary_formats);
>> +		intel_format_modifiers = skl_format_modifiers;
>>
>>  		primary->update_plane = skylake_update_primary_plane;
>>  		primary->disable_plane = skylake_disable_primary_plane;
>>  	} else if (HAS_PCH_SPLIT(dev_priv)) {
>>  		intel_primary_formats = i965_primary_formats;
>>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> +		intel_format_modifiers = i965_format_modifiers;
>>
>>  		primary->update_plane = ironlake_update_primary_plane;
>>  		primary->disable_plane = i9xx_disable_primary_plane;
>>  	} else if (INTEL_GEN(dev_priv) >= 4) {
>>  		intel_primary_formats = i965_primary_formats;
>>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> +		intel_format_modifiers = i965_format_modifiers;
>>
>>  		primary->update_plane = i9xx_update_primary_plane;
>>  		primary->disable_plane = i9xx_disable_primary_plane;
>>  	} else {
>>  		intel_primary_formats = i8xx_primary_formats;
>>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
>> +		intel_format_modifiers = i8xx_format_modifiers;
>>
>>  		primary->update_plane = i9xx_update_primary_plane;
>>  		primary->disable_plane = i9xx_disable_primary_plane;
>> @@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>>  					       0, &intel_plane_funcs,
>>  					       intel_primary_formats, num_formats,
>> -					       NULL,
>> +					       intel_format_modifiers,
>>  					       DRM_PLANE_TYPE_PRIMARY,
>>  					       "plane 1%c", pipe_name(pipe));
>>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>>  					       0, &intel_plane_funcs,
>>  					       intel_primary_formats, num_formats,
>> -					       NULL,
>> +					       intel_format_modifiers,
>>  					       DRM_PLANE_TYPE_PRIMARY,
>>  					       "primary %c", pipe_name(pipe));
>>  	else
>>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>>  					       0, &intel_plane_funcs,
>>  					       intel_primary_formats, num_formats,
>> -					       NULL,
>> +					       intel_format_modifiers,
>>  					       DRM_PLANE_TYPE_PRIMARY,
>>  					       "plane %c", plane_name(primary->plane));
>>  	if (ret)
>> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> index 1c2f26d86f76..152ec8196d41 100644
>> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> @@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
>>  	DRM_FORMAT_VYUY,
>>  };
>>
>> +static const uint64_t ilk_plane_format_modifiers[] = {
>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  static const uint32_t snb_plane_formats[] = {
>>  	DRM_FORMAT_XBGR8888,
>>  	DRM_FORMAT_XRGB8888,
>> @@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
>>  	DRM_FORMAT_VYUY,
>>  };
>>
>> +static const uint64_t snb_plane_format_modifiers[] = {
>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  static const uint32_t vlv_plane_formats[] = {
>>  	DRM_FORMAT_RGB565,
>>  	DRM_FORMAT_ABGR8888,
>> @@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
>>  	DRM_FORMAT_VYUY,
>>  };
>>
>> +static const uint64_t vlv_plane_format_modifiers[] = {
>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  static uint32_t skl_plane_formats[] = {
>>  	DRM_FORMAT_RGB565,
>>  	DRM_FORMAT_ABGR8888,
>> @@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
>>  	DRM_FORMAT_VYUY,
>>  };
>>
>> +static const uint64_t skl_plane_format_modifiers[] = {
>> +	I915_FORMAT_MOD_Y_TILED,
>> +	I915_FORMAT_MOD_X_TILED,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>>  struct intel_plane *
>>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>  			  enum pipe pipe, int plane)
>> @@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>  	struct intel_plane_state *state = NULL;
>>  	unsigned long possible_crtcs;
>>  	const uint32_t *plane_formats;
>> +	const uint64_t *modifiers;
>>  	unsigned int supported_rotations;
>>  	int num_plane_formats;
>>  	int ret;
>> @@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>
>>  		plane_formats = skl_plane_formats;
>>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
>> +		modifiers = skl_plane_format_modifiers;
>>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>>  		intel_plane->can_scale = false;
>>  		intel_plane->max_downscale = 1;
>> @@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>
>>  		plane_formats = vlv_plane_formats;
>>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
>> +		modifiers = vlv_plane_format_modifiers;
>>  	} else if (INTEL_GEN(dev_priv) >= 7) {
>>  		if (IS_IVYBRIDGE(dev_priv)) {
>>  			intel_plane->can_scale = true;
>> @@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>
>>  		plane_formats = snb_plane_formats;
>>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> +		modifiers = snb_plane_format_modifiers;
>>  	} else {
>>  		intel_plane->can_scale = true;
>>  		intel_plane->max_downscale = 16;
>> @@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>  		if (IS_GEN6(dev_priv)) {
>>  			plane_formats = snb_plane_formats;
>>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> +			modifiers = snb_plane_format_modifiers;
>>  		} else {
>>  			plane_formats = ilk_plane_formats;
>>  			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
>> +			modifiers = ilk_plane_format_modifiers;
>>  		}
>>  	}
>>
>> @@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>>  					       possible_crtcs, &intel_plane_funcs,
>>  					       plane_formats, num_plane_formats,
>> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> +					       modifiers,
>> +					       DRM_PLANE_TYPE_OVERLAY,
>>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>>  	else
>>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>>  					       possible_crtcs, &intel_plane_funcs,
>>  					       plane_formats, num_plane_formats,
>> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> +					       modifiers,
>> +					       DRM_PLANE_TYPE_OVERLAY,
>>  					       "sprite %c", sprite_name(pipe, plane));
>>  	if (ret)
>>  		goto fail;
>> --
>> 2.11.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>-- 
>Ville Syrjälä
>Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 17:50             ` Daniel Stone
@ 2017-01-12 18:11               ` Ville Syrjälä
  2017-01-12 19:27                 ` Daniel Stone
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12 18:11 UTC (permalink / raw)
  To: Daniel Stone; +Cc: Intel GFX, Ben Widawsky, DRI Development

On Thu, Jan 12, 2017 at 05:50:15PM +0000, Daniel Stone wrote:
> Hi,
> 
> On 12 January 2017 at 17:45, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
> > On Thu, Jan 12, 2017 at 05:04:46PM +0000, Daniel Stone wrote:
> >> Implicit is clever but horrible. AFAICT, the only way to do it
> >> properly would be to have a nested forwards loop walk when you first
> >> hit a modifier, searching for further occurrences of that modifier to
> >> collect the complete set of formats that modifier applies to.
> >
> > Not sure for what that is the "only way". In fact I can't right now
> > think of any operation that would require an extra loop necessarily.
> > For some things you might just want to look for a specific
> > format+modifier combo, for that it doesn't matter how many blocks there
> > are.
> 
> Right, that just needs a local variable to act as a counter.
> 
> > And if you want to transform the reply into some less convoluted
> > form, well then you'd just need some modifier+dynamic format list thing,
> > or if you want to keep to bitmasks you'd either need a bitmask that can
> > grow when running out of bits or just make it big enough to handle a
> > sufficiently large worst case number of bits.
> >
> > Dunno, maybe I just lack imagination. Then again, I'm not even sure if
> > we're talking about userspace of kernel code here, which might explain
> > my general confusion :)
> 
> I'm talking about userspace, where I want to have:
> struct drm_plane {
>     struct {
>         uint32_t format;
>         uint64_t modifiers[];
>     } formats[];
> }

Flipping formats[] vs. modifiers[] here would seem like it should make
this easier with the proposed kernel API. And if the kernel will also
uarantee that multiple instances of the same modifier must be returned
contiguously, then it should be even easier.

Oh and flipping formats[] and modifiers[] should also save a quite a
bit of space since each format takes twice as much space as each
modifier. But I suppose that might come at a runtime cost if you have
to look for a specific format in each modifier's format list instead
of having to look at just the modifier list of a specific format. So
I suppose not flipping might be better after all, which I guess would
complicate populating the infromation somewhat.

Anyways, that's all a bit unrelated to the matter at hand, so I'll stop
now and just state that I don't mind having an explicit offset if
people really want it.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12 18:00     ` Ben Widawsky
@ 2017-01-12 18:32       ` Ville Syrjälä
  2017-01-12 18:56         ` Ben Widawsky
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-12 18:32 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Kristian H . Kristensen, DRI Development

On Thu, Jan 12, 2017 at 10:00:55AM -0800, Ben Widawsky wrote:
> On 17-01-12 12:51:20, Ville Syrjälä wrote:
> >On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
> >> This was based on a patch originally by Kristian. It has been modified
> >> pretty heavily to use the new callbacks from the previous patch.
> >>
> >> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
> >> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> >> ---
> >>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
> >>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
> >>  2 files changed, 137 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> index 8715b1083d1d..26f3a911b999 100644
> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
> >>  	DRM_FORMAT_XRGB8888,
> >>  };
> >>
> >> +static const uint64_t i8xx_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_X_TILED,
> >
> >Did we want to list the linear modifier in these as well?
> >
> 
> Yeah. My initial response was no, but yes. We should. I was using
> DRM_FORMAT_MOD_NONE in its place, it should be linear, and it should be defined
> in the array.
> 
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  /* Primary plane formats for gen >= 4 */
> >>  static const uint32_t i965_primary_formats[] = {
> >>  	DRM_FORMAT_C8,
> >> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
> >>  	DRM_FORMAT_XBGR2101010,
> >>  };
> >>
> >> +static const uint64_t i965_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >
> >We could just share the i8xx array. The name of the array should perhaps
> >be i9xx_format_modifiers[] in that case. That's sort of the naming
> >convention we've been left with for things that apply to more or less
> >all the platforms.
> >
> 
> Got it thanks. This is a relic from Kristian's original patch which tied the
> modifiers to the formats in place. It made more sense there to have a separate
> i8xx
> 
> >> +
> >>  static const uint32_t skl_primary_formats[] = {
> >>  	DRM_FORMAT_C8,
> >>  	DRM_FORMAT_RGB565,
> >> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
> >>  	DRM_FORMAT_VYUY,
> >>  };
> >>
> >> +static const uint64_t skl_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_Y_TILED,
> >
> >Yf missing? and linear
> >
> 
> Yes, thanks. I'm kind of scared to add Yf to be honest :P
> 
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  /* Cursor formats */
> >>  static const uint32_t intel_cursor_formats[] = {
> >>  	DRM_FORMAT_ARGB8888,
> >> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
> >>  	kfree(to_intel_plane(plane));
> >>  }
> >>
> >> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
> >> +{
> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
> >> +		return true;
> >> +
> >> +	switch (format) {
> >> +	case DRM_FORMAT_C8:
> >> +	case DRM_FORMAT_RGB565:
> >> +	case DRM_FORMAT_XRGB1555:
> >> +	case DRM_FORMAT_XRGB8888:
> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> +	default:
> >> +		return false;
> >> +	}
> >> +}
> >> +
> >> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
> >> +{
> >> +	switch (format) {
> >> +	case DRM_FORMAT_C8:
> >> +	case DRM_FORMAT_RGB565:
> >> +	case DRM_FORMAT_XRGB8888:
> >> +	case DRM_FORMAT_XBGR8888:
> >> +	case DRM_FORMAT_XRGB2101010:
> >> +	case DRM_FORMAT_XBGR2101010:
> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> +	default:
> >> +		return false;
> >> +	}
> >> +}
> >
> >Hmm. There should be no format vs. tiling restrictions on these
> >platforms, so presumably a simple "return true" should cover it all.
> >That does perhaps remove the usefulness of these functions for
> >verifying that the format or modifier is supported at all
> 
> One of the reasons for changing to this current format-modifier lookup at all
> was Kristian's approach was considered fragile. If for whatever reason formats
> are added, or removed, we'll catch it here. Also, it maybe let's us do something
> on cursor plane at some point (I don't actually know). So yeah, we can return
> true, but I like that it's spelled out explicitly. Makes it easy to compare it
> to the docs as well to make sure our code is correct.
> 
> The benefit is of course I can combine i965_mod_supported() with
> i8xx_mod_supported()
> 
> I'm honestly fine with changing it as well, I just don't see a huge reason to
> change it since I've already typed it up. I'll leave it to you.

Feel free to keep it. We can always change it later if it becomes too much
work to maintain the duplicated format lists (the function and the array).
Not that I really expect these lists to be all that volatile.

> 
> [ ] Yes, change it.
> [ ] No, leave it.
> 
> >but I've been thinking that addfb should perhaps just iterate through the
> >format and modifier lists for every plane. Would avoid having to effectively
> >maintain the same lists in multiple places.
> >
> 
> I don't quite follow this. Can you elaborate?

I was just thinking that instead of addfb passing in an unverified format
to the driver's .fb_create() hook, it could first go through the format
lists of each plane, and make sure at least one of them supports the
requested format. That way we could eliminate that fragile pixel_format
switch statement from intel_framebuffer_init().

But if you plan on making the .format_mod_supported() hooks 100%
strict, then we could use that instead. Would avoid having to walk
the format lists of every plane at least.

> 
> >> +
> >> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
> >> +{
> >> +	switch (format) {
> >> +	case DRM_FORMAT_C8:
> >> +	case DRM_FORMAT_RGB565:
> >> +	case DRM_FORMAT_XRGB8888:
> >> +	case DRM_FORMAT_XBGR8888:
> >> +	case DRM_FORMAT_ARGB8888:
> >> +	case DRM_FORMAT_ABGR8888:
> >> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
> >> +			modifier == I915_FORMAT_MOD_X_TILED;
> >> +	case DRM_FORMAT_XRGB2101010:
> >> +	case DRM_FORMAT_XBGR2101010:
> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> +	case DRM_FORMAT_YUYV:
> >> +	case DRM_FORMAT_YVYU:
> >> +	case DRM_FORMAT_UYVY:
> >> +	case DRM_FORMAT_VYUY:
> >
> >IIRC on SKL the only restrictions should be that CCS modifiers are
> >limited to 8:8:8:8 formats only. Other modifiers should work
> >with any format.
> >
> 
> This restriction was copied from Kristian's patch. I just checked the docs and
> you are correct. So this needs Yf modifier too. (Aside from CCS, rotation is the
> one case: x-tiled 1010102 isn't supported).

I can't see any extra restrictions for 10bpc formats.

The only exception I see for 0/180 degree rotation is FP16 not being
supported with Yf. And since we don't actually expose FP16 we don't have
to worry about it. So apart from the CCS+8:8:8:8 cases all other
format+modifier combos should be perfectly fine AFAICS.

My information was gleaned from the "plane capability" table in the
spec, but I wasn't able to immediately spot any additional restriction
in the PLANE_CTL register description either.

> 
> >> +	default:
> >> +		return false;
> >> +	}
> >> +
> >> +}
> >> +
> >> +static bool intel_plane_format_mod_supported(struct drm_plane *plane,
> >> +					     uint32_t format,
> >> +					     uint64_t modifier)
> >> +{
> >> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
> >> +
> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
> >> +		return true;
> >> +
> >> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> >> +		return false;
> >> +
> >> +	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
> >> +		    plane->type != DRM_PLANE_TYPE_OVERLAY))
> >> +	    return false;
> >> +
> >> +	if (INTEL_GEN(dev_priv) >= 9)
> >> +		return skl_mod_supported(format, modifier);
> >> +	else if (INTEL_GEN(dev_priv) >= 4)
> >> +		return i965_mod_supported(format, modifier);
> >> +	else
> >> +		return i8xx_mod_supported(format, modifier);
> >> +
> >> +	return false;
> >> +}
> >> +
> >>  const struct drm_plane_funcs intel_plane_funcs = {
> >>  	.update_plane = drm_atomic_helper_update_plane,
> >>  	.disable_plane = drm_atomic_helper_disable_plane,
> >> @@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
> >>  	.atomic_set_property = intel_plane_atomic_set_property,
> >>  	.atomic_duplicate_state = intel_plane_duplicate_state,
> >>  	.atomic_destroy_state = intel_plane_destroy_state,
> >> +	.format_mod_supported = intel_plane_format_mod_supported,
> >>  };
> >>
> >>  static int
> >> @@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> >>  	const uint32_t *intel_primary_formats;
> >>  	unsigned int supported_rotations;
> >>  	unsigned int num_formats;
> >> +	const uint64_t *intel_format_modifiers;
> >>  	int ret;
> >>
> >>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> >> @@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> >>  	if (INTEL_GEN(dev_priv) >= 9) {
> >>  		intel_primary_formats = skl_primary_formats;
> >>  		num_formats = ARRAY_SIZE(skl_primary_formats);
> >> +		intel_format_modifiers = skl_format_modifiers;
> >>
> >>  		primary->update_plane = skylake_update_primary_plane;
> >>  		primary->disable_plane = skylake_disable_primary_plane;
> >>  	} else if (HAS_PCH_SPLIT(dev_priv)) {
> >>  		intel_primary_formats = i965_primary_formats;
> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
> >> +		intel_format_modifiers = i965_format_modifiers;
> >>
> >>  		primary->update_plane = ironlake_update_primary_plane;
> >>  		primary->disable_plane = i9xx_disable_primary_plane;
> >>  	} else if (INTEL_GEN(dev_priv) >= 4) {
> >>  		intel_primary_formats = i965_primary_formats;
> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
> >> +		intel_format_modifiers = i965_format_modifiers;
> >>
> >>  		primary->update_plane = i9xx_update_primary_plane;
> >>  		primary->disable_plane = i9xx_disable_primary_plane;
> >>  	} else {
> >>  		intel_primary_formats = i8xx_primary_formats;
> >>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
> >> +		intel_format_modifiers = i8xx_format_modifiers;
> >>
> >>  		primary->update_plane = i9xx_update_primary_plane;
> >>  		primary->disable_plane = i9xx_disable_primary_plane;
> >> @@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
> >>  					       0, &intel_plane_funcs,
> >>  					       intel_primary_formats, num_formats,
> >> -					       NULL,
> >> +					       intel_format_modifiers,
> >>  					       DRM_PLANE_TYPE_PRIMARY,
> >>  					       "plane 1%c", pipe_name(pipe));
> >>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
> >>  					       0, &intel_plane_funcs,
> >>  					       intel_primary_formats, num_formats,
> >> -					       NULL,
> >> +					       intel_format_modifiers,
> >>  					       DRM_PLANE_TYPE_PRIMARY,
> >>  					       "primary %c", pipe_name(pipe));
> >>  	else
> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
> >>  					       0, &intel_plane_funcs,
> >>  					       intel_primary_formats, num_formats,
> >> -					       NULL,
> >> +					       intel_format_modifiers,
> >>  					       DRM_PLANE_TYPE_PRIMARY,
> >>  					       "plane %c", plane_name(primary->plane));
> >>  	if (ret)
> >> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> >> index 1c2f26d86f76..152ec8196d41 100644
> >> --- a/drivers/gpu/drm/i915/intel_sprite.c
> >> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> >> @@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
> >>  	DRM_FORMAT_VYUY,
> >>  };
> >>
> >> +static const uint64_t ilk_plane_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  static const uint32_t snb_plane_formats[] = {
> >>  	DRM_FORMAT_XBGR8888,
> >>  	DRM_FORMAT_XRGB8888,
> >> @@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
> >>  	DRM_FORMAT_VYUY,
> >>  };
> >>
> >> +static const uint64_t snb_plane_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  static const uint32_t vlv_plane_formats[] = {
> >>  	DRM_FORMAT_RGB565,
> >>  	DRM_FORMAT_ABGR8888,
> >> @@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
> >>  	DRM_FORMAT_VYUY,
> >>  };
> >>
> >> +static const uint64_t vlv_plane_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  static uint32_t skl_plane_formats[] = {
> >>  	DRM_FORMAT_RGB565,
> >>  	DRM_FORMAT_ABGR8888,
> >> @@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
> >>  	DRM_FORMAT_VYUY,
> >>  };
> >>
> >> +static const uint64_t skl_plane_format_modifiers[] = {
> >> +	I915_FORMAT_MOD_Y_TILED,
> >> +	I915_FORMAT_MOD_X_TILED,
> >> +	DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >>  struct intel_plane *
> >>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>  			  enum pipe pipe, int plane)
> >> @@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>  	struct intel_plane_state *state = NULL;
> >>  	unsigned long possible_crtcs;
> >>  	const uint32_t *plane_formats;
> >> +	const uint64_t *modifiers;
> >>  	unsigned int supported_rotations;
> >>  	int num_plane_formats;
> >>  	int ret;
> >> @@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>
> >>  		plane_formats = skl_plane_formats;
> >>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
> >> +		modifiers = skl_plane_format_modifiers;
> >>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> >>  		intel_plane->can_scale = false;
> >>  		intel_plane->max_downscale = 1;
> >> @@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>
> >>  		plane_formats = vlv_plane_formats;
> >>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
> >> +		modifiers = vlv_plane_format_modifiers;
> >>  	} else if (INTEL_GEN(dev_priv) >= 7) {
> >>  		if (IS_IVYBRIDGE(dev_priv)) {
> >>  			intel_plane->can_scale = true;
> >> @@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>
> >>  		plane_formats = snb_plane_formats;
> >>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> >> +		modifiers = snb_plane_format_modifiers;
> >>  	} else {
> >>  		intel_plane->can_scale = true;
> >>  		intel_plane->max_downscale = 16;
> >> @@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>  		if (IS_GEN6(dev_priv)) {
> >>  			plane_formats = snb_plane_formats;
> >>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> >> +			modifiers = snb_plane_format_modifiers;
> >>  		} else {
> >>  			plane_formats = ilk_plane_formats;
> >>  			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
> >> +			modifiers = ilk_plane_format_modifiers;
> >>  		}
> >>  	}
> >>
> >> @@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
> >>  					       possible_crtcs, &intel_plane_funcs,
> >>  					       plane_formats, num_plane_formats,
> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> >> +					       modifiers,
> >> +					       DRM_PLANE_TYPE_OVERLAY,
> >>  					       "plane %d%c", plane + 2, pipe_name(pipe));
> >>  	else
> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
> >>  					       possible_crtcs, &intel_plane_funcs,
> >>  					       plane_formats, num_plane_formats,
> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> >> +					       modifiers,
> >> +					       DRM_PLANE_TYPE_OVERLAY,
> >>  					       "sprite %c", sprite_name(pipe, plane));
> >>  	if (ret)
> >>  		goto fail;
> >> --
> >> 2.11.0
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> >
> >-- 
> >Ville Syrjälä
> >Intel OTC

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12 18:32       ` Ville Syrjälä
@ 2017-01-12 18:56         ` Ben Widawsky
  2017-01-13  9:35           ` Ville Syrjälä
  0 siblings, 1 reply; 28+ messages in thread
From: Ben Widawsky @ 2017-01-12 18:56 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: Intel GFX, Kristian H . Kristensen, DRI Development

On 17-01-12 20:32:07, Ville Syrjälä wrote:
>On Thu, Jan 12, 2017 at 10:00:55AM -0800, Ben Widawsky wrote:
>> On 17-01-12 12:51:20, Ville Syrjälä wrote:
>> >On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
>> >> This was based on a patch originally by Kristian. It has been modified
>> >> pretty heavily to use the new callbacks from the previous patch.
>> >>
>> >> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
>> >> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
>> >> ---
>> >>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
>> >>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
>> >>  2 files changed, 137 insertions(+), 5 deletions(-)
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> >> index 8715b1083d1d..26f3a911b999 100644
>> >> --- a/drivers/gpu/drm/i915/intel_display.c
>> >> +++ b/drivers/gpu/drm/i915/intel_display.c
>> >> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
>> >>  	DRM_FORMAT_XRGB8888,
>> >>  };
>> >>
>> >> +static const uint64_t i8xx_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >
>> >Did we want to list the linear modifier in these as well?
>> >
>>
>> Yeah. My initial response was no, but yes. We should. I was using
>> DRM_FORMAT_MOD_NONE in its place, it should be linear, and it should be defined
>> in the array.
>>
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  /* Primary plane formats for gen >= 4 */
>> >>  static const uint32_t i965_primary_formats[] = {
>> >>  	DRM_FORMAT_C8,
>> >> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
>> >>  	DRM_FORMAT_XBGR2101010,
>> >>  };
>> >>
>> >> +static const uint64_t i965_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >
>> >We could just share the i8xx array. The name of the array should perhaps
>> >be i9xx_format_modifiers[] in that case. That's sort of the naming
>> >convention we've been left with for things that apply to more or less
>> >all the platforms.
>> >
>>
>> Got it thanks. This is a relic from Kristian's original patch which tied the
>> modifiers to the formats in place. It made more sense there to have a separate
>> i8xx
>>
>> >> +
>> >>  static const uint32_t skl_primary_formats[] = {
>> >>  	DRM_FORMAT_C8,
>> >>  	DRM_FORMAT_RGB565,
>> >> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t skl_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_Y_TILED,
>> >
>> >Yf missing? and linear
>> >
>>
>> Yes, thanks. I'm kind of scared to add Yf to be honest :P
>>
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  /* Cursor formats */
>> >>  static const uint32_t intel_cursor_formats[] = {
>> >>  	DRM_FORMAT_ARGB8888,
>> >> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
>> >>  	kfree(to_intel_plane(plane));
>> >>  }
>> >>
>> >> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> >> +		return true;
>> >> +
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB1555:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +}
>> >> +
>> >> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +	case DRM_FORMAT_XBGR8888:
>> >> +	case DRM_FORMAT_XRGB2101010:
>> >> +	case DRM_FORMAT_XBGR2101010:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +}
>> >
>> >Hmm. There should be no format vs. tiling restrictions on these
>> >platforms, so presumably a simple "return true" should cover it all.
>> >That does perhaps remove the usefulness of these functions for
>> >verifying that the format or modifier is supported at all
>>
>> One of the reasons for changing to this current format-modifier lookup at all
>> was Kristian's approach was considered fragile. If for whatever reason formats
>> are added, or removed, we'll catch it here. Also, it maybe let's us do something
>> on cursor plane at some point (I don't actually know). So yeah, we can return
>> true, but I like that it's spelled out explicitly. Makes it easy to compare it
>> to the docs as well to make sure our code is correct.
>>
>> The benefit is of course I can combine i965_mod_supported() with
>> i8xx_mod_supported()
>>
>> I'm honestly fine with changing it as well, I just don't see a huge reason to
>> change it since I've already typed it up. I'll leave it to you.
>
>Feel free to keep it. We can always change it later if it becomes too much
>work to maintain the duplicated format lists (the function and the array).
>Not that I really expect these lists to be all that volatile.
>
>>
>> [ ] Yes, change it.
>> [ ] No, leave it.
>>
>> >but I've been thinking that addfb should perhaps just iterate through the
>> >format and modifier lists for every plane. Would avoid having to effectively
>> >maintain the same lists in multiple places.
>> >
>>
>> I don't quite follow this. Can you elaborate?
>
>I was just thinking that instead of addfb passing in an unverified format
>to the driver's .fb_create() hook, it could first go through the format
>lists of each plane, and make sure at least one of them supports the
>requested format. That way we could eliminate that fragile pixel_format
>switch statement from intel_framebuffer_init().
>
>But if you plan on making the .format_mod_supported() hooks 100%
>strict, then we could use that instead. Would avoid having to walk
>the format lists of every plane at least.
>

Let's keep it the way things are for now, mostly because I'm lazy and this
works.

>>
>> >> +
>> >> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +	case DRM_FORMAT_XBGR8888:
>> >> +	case DRM_FORMAT_ARGB8888:
>> >> +	case DRM_FORMAT_ABGR8888:
>> >> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
>> >> +			modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	case DRM_FORMAT_XRGB2101010:
>> >> +	case DRM_FORMAT_XBGR2101010:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	case DRM_FORMAT_YUYV:
>> >> +	case DRM_FORMAT_YVYU:
>> >> +	case DRM_FORMAT_UYVY:
>> >> +	case DRM_FORMAT_VYUY:
>> >
>> >IIRC on SKL the only restrictions should be that CCS modifiers are
>> >limited to 8:8:8:8 formats only. Other modifiers should work
>> >with any format.
>> >
>>
>> This restriction was copied from Kristian's patch. I just checked the docs and
>> you are correct. So this needs Yf modifier too. (Aside from CCS, rotation is the
>> one case: x-tiled 1010102 isn't supported).
>
>I can't see any extra restrictions for 10bpc formats.
>
>The only exception I see for 0/180 degree rotation is FP16 not being
>supported with Yf. And since we don't actually expose FP16 we don't have
>to worry about it. So apart from the CCS+8:8:8:8 cases all other
>format+modifier combos should be perfectly fine AFAICS.
>
>My information was gleaned from the "plane capability" table in the
>spec, but I wasn't able to immediately spot any additional restriction
>in the PLANE_CTL register description either.
>

Sorry for making you verify that, I think you are correct and I'm misreading the
table. I was just looking at the specific columns: Linear and X-tiled 90/270
rotation aren't supported with 1010102, but they aren't supported with any other
surface format either.

However, looking again now, it looks like DRM_FORMAT_C8 doesn't support Yf.

>>
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +
>> >> +}
>> >> +
>> >> +static bool intel_plane_format_mod_supported(struct drm_plane *plane,
>> >> +					     uint32_t format,
>> >> +					     uint64_t modifier)
>> >> +{
>> >> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
>> >> +
>> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> >> +		return true;
>> >> +
>> >> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
>> >> +		return false;
>> >> +
>> >> +	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
>> >> +		    plane->type != DRM_PLANE_TYPE_OVERLAY))
>> >> +	    return false;
>> >> +
>> >> +	if (INTEL_GEN(dev_priv) >= 9)
>> >> +		return skl_mod_supported(format, modifier);
>> >> +	else if (INTEL_GEN(dev_priv) >= 4)
>> >> +		return i965_mod_supported(format, modifier);
>> >> +	else
>> >> +		return i8xx_mod_supported(format, modifier);
>> >> +
>> >> +	return false;
>> >> +}
>> >> +
>> >>  const struct drm_plane_funcs intel_plane_funcs = {
>> >>  	.update_plane = drm_atomic_helper_update_plane,
>> >>  	.disable_plane = drm_atomic_helper_disable_plane,
>> >> @@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
>> >>  	.atomic_set_property = intel_plane_atomic_set_property,
>> >>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>> >>  	.atomic_destroy_state = intel_plane_destroy_state,
>> >> +	.format_mod_supported = intel_plane_format_mod_supported,
>> >>  };
>> >>
>> >>  static int
>> >> @@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  	const uint32_t *intel_primary_formats;
>> >>  	unsigned int supported_rotations;
>> >>  	unsigned int num_formats;
>> >> +	const uint64_t *intel_format_modifiers;
>> >>  	int ret;
>> >>
>> >>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
>> >> @@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  	if (INTEL_GEN(dev_priv) >= 9) {
>> >>  		intel_primary_formats = skl_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(skl_primary_formats);
>> >> +		intel_format_modifiers = skl_format_modifiers;
>> >>
>> >>  		primary->update_plane = skylake_update_primary_plane;
>> >>  		primary->disable_plane = skylake_disable_primary_plane;
>> >>  	} else if (HAS_PCH_SPLIT(dev_priv)) {
>> >>  		intel_primary_formats = i965_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> >> +		intel_format_modifiers = i965_format_modifiers;
>> >>
>> >>  		primary->update_plane = ironlake_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >>  	} else if (INTEL_GEN(dev_priv) >= 4) {
>> >>  		intel_primary_formats = i965_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> >> +		intel_format_modifiers = i965_format_modifiers;
>> >>
>> >>  		primary->update_plane = i9xx_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >>  	} else {
>> >>  		intel_primary_formats = i8xx_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
>> >> +		intel_format_modifiers = i8xx_format_modifiers;
>> >>
>> >>  		primary->update_plane = i9xx_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >> @@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "plane 1%c", pipe_name(pipe));
>> >>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "primary %c", pipe_name(pipe));
>> >>  	else
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "plane %c", plane_name(primary->plane));
>> >>  	if (ret)
>> >> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> >> index 1c2f26d86f76..152ec8196d41 100644
>> >> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> >> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> >> @@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t ilk_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static const uint32_t snb_plane_formats[] = {
>> >>  	DRM_FORMAT_XBGR8888,
>> >>  	DRM_FORMAT_XRGB8888,
>> >> @@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t snb_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static const uint32_t vlv_plane_formats[] = {
>> >>  	DRM_FORMAT_RGB565,
>> >>  	DRM_FORMAT_ABGR8888,
>> >> @@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t vlv_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static uint32_t skl_plane_formats[] = {
>> >>  	DRM_FORMAT_RGB565,
>> >>  	DRM_FORMAT_ABGR8888,
>> >> @@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t skl_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_Y_TILED,
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  struct intel_plane *
>> >>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  			  enum pipe pipe, int plane)
>> >> @@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  	struct intel_plane_state *state = NULL;
>> >>  	unsigned long possible_crtcs;
>> >>  	const uint32_t *plane_formats;
>> >> +	const uint64_t *modifiers;
>> >>  	unsigned int supported_rotations;
>> >>  	int num_plane_formats;
>> >>  	int ret;
>> >> @@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = skl_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
>> >> +		modifiers = skl_plane_format_modifiers;
>> >>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>> >>  		intel_plane->can_scale = false;
>> >>  		intel_plane->max_downscale = 1;
>> >> @@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = vlv_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
>> >> +		modifiers = vlv_plane_format_modifiers;
>> >>  	} else if (INTEL_GEN(dev_priv) >= 7) {
>> >>  		if (IS_IVYBRIDGE(dev_priv)) {
>> >>  			intel_plane->can_scale = true;
>> >> @@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = snb_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> >> +		modifiers = snb_plane_format_modifiers;
>> >>  	} else {
>> >>  		intel_plane->can_scale = true;
>> >>  		intel_plane->max_downscale = 16;
>> >> @@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  		if (IS_GEN6(dev_priv)) {
>> >>  			plane_formats = snb_plane_formats;
>> >>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> >> +			modifiers = snb_plane_format_modifiers;
>> >>  		} else {
>> >>  			plane_formats = ilk_plane_formats;
>> >>  			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
>> >> +			modifiers = ilk_plane_format_modifiers;
>> >>  		}
>> >>  	}
>> >>
>> >> @@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>> >>  					       possible_crtcs, &intel_plane_funcs,
>> >>  					       plane_formats, num_plane_formats,
>> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> >> +					       modifiers,
>> >> +					       DRM_PLANE_TYPE_OVERLAY,
>> >>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>> >>  	else
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>> >>  					       possible_crtcs, &intel_plane_funcs,
>> >>  					       plane_formats, num_plane_formats,
>> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> >> +					       modifiers,
>> >> +					       DRM_PLANE_TYPE_OVERLAY,
>> >>  					       "sprite %c", sprite_name(pipe, plane));
>> >>  	if (ret)
>> >>  		goto fail;
>> >> --
>> >> 2.11.0
>> >>
>> >> _______________________________________________
>> >> dri-devel mailing list
>> >> dri-devel@lists.freedesktop.org
>> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>> >
>> >--
>> >Ville Syrjälä
>> >Intel OTC
>
>-- 
>Ville Syrjälä
>Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 18:11               ` Ville Syrjälä
@ 2017-01-12 19:27                 ` Daniel Stone
  2017-01-13  9:37                   ` [Intel-gfx] " Ville Syrjälä
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Stone @ 2017-01-12 19:27 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel GFX, Ben Widawsky, DRI Development

Hi,

On 12 January 2017 at 18:11, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> On Thu, Jan 12, 2017 at 05:50:15PM +0000, Daniel Stone wrote:
>> struct drm_plane {
>>     struct {
>>         uint32_t format;
>>         uint64_t modifiers[];
>>     } formats[];
>> }
>
> Flipping formats[] vs. modifiers[] here would seem like it should make
> this easier with the proposed kernel API. And if the kernel will also
> uarantee that multiple instances of the same modifier must be returned
> contiguously, then it should be even easier.
>
> Oh and flipping formats[] and modifiers[] should also save a quite a
> bit of space since each format takes twice as much space as each
> modifier. But I suppose that might come at a runtime cost if you have
> to look for a specific format in each modifier's format list instead
> of having to look at just the modifier list of a specific format. So
> I suppose not flipping might be better after all, which I guess would
> complicate populating the infromation somewhat.
>
> Anyways, that's all a bit unrelated to the matter at hand, so I'll stop
> now and just state that I don't mind having an explicit offset if
> people really want it.

It would make sense, but then gbm_surface_create_with_modifiers takes
a fixed pixel format and a list of acceptable modifiers (which to me
seems like the right way around as an API), so whenever I was creating
a surface, I'd have to walk through and create a new list, flipped
back the other way.

Cheers,
Daniel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] drm/i915: Add format modifiers for Intel
  2017-01-12 18:56         ` Ben Widawsky
@ 2017-01-13  9:35           ` Ville Syrjälä
  0 siblings, 0 replies; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-13  9:35 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Kristian H . Kristensen, DRI Development

On Thu, Jan 12, 2017 at 10:56:17AM -0800, Ben Widawsky wrote:
> On 17-01-12 20:32:07, Ville Syrjälä wrote:
> >On Thu, Jan 12, 2017 at 10:00:55AM -0800, Ben Widawsky wrote:
> >> On 17-01-12 12:51:20, Ville Syrjälä wrote:
> >> >On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
> >> >> This was based on a patch originally by Kristian. It has been modified
> >> >> pretty heavily to use the new callbacks from the previous patch.
> >> >>
> >> >> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
> >> >> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> >> >> ---
> >> >>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
> >> >>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
> >> >>  2 files changed, 137 insertions(+), 5 deletions(-)
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> >> index 8715b1083d1d..26f3a911b999 100644
> >> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> >> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
> >> >>  	DRM_FORMAT_XRGB8888,
> >> >>  };
> >> >>
> >> >> +static const uint64_t i8xx_format_modifiers[] = {
> >> >> +	I915_FORMAT_MOD_X_TILED,
> >> >
> >> >Did we want to list the linear modifier in these as well?
> >> >
> >>
> >> Yeah. My initial response was no, but yes. We should. I was using
> >> DRM_FORMAT_MOD_NONE in its place, it should be linear, and it should be defined
> >> in the array.
> >>
> >> >> +	DRM_FORMAT_MOD_INVALID
> >> >> +};
> >> >> +
> >> >>  /* Primary plane formats for gen >= 4 */
> >> >>  static const uint32_t i965_primary_formats[] = {
> >> >>  	DRM_FORMAT_C8,
> >> >> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
> >> >>  	DRM_FORMAT_XBGR2101010,
> >> >>  };
> >> >>
> >> >> +static const uint64_t i965_format_modifiers[] = {
> >> >> +	I915_FORMAT_MOD_X_TILED,
> >> >> +	DRM_FORMAT_MOD_INVALID
> >> >> +};
> >> >
> >> >We could just share the i8xx array. The name of the array should perhaps
> >> >be i9xx_format_modifiers[] in that case. That's sort of the naming
> >> >convention we've been left with for things that apply to more or less
> >> >all the platforms.
> >> >
> >>
> >> Got it thanks. This is a relic from Kristian's original patch which tied the
> >> modifiers to the formats in place. It made more sense there to have a separate
> >> i8xx
> >>
> >> >> +
> >> >>  static const uint32_t skl_primary_formats[] = {
> >> >>  	DRM_FORMAT_C8,
> >> >>  	DRM_FORMAT_RGB565,
> >> >> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
> >> >>  	DRM_FORMAT_VYUY,
> >> >>  };
> >> >>
> >> >> +static const uint64_t skl_format_modifiers[] = {
> >> >> +	I915_FORMAT_MOD_Y_TILED,
> >> >
> >> >Yf missing? and linear
> >> >
> >>
> >> Yes, thanks. I'm kind of scared to add Yf to be honest :P
> >>
> >> >> +	I915_FORMAT_MOD_X_TILED,
> >> >> +	DRM_FORMAT_MOD_INVALID
> >> >> +};
> >> >> +
> >> >>  /* Cursor formats */
> >> >>  static const uint32_t intel_cursor_formats[] = {
> >> >>  	DRM_FORMAT_ARGB8888,
> >> >> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
> >> >>  	kfree(to_intel_plane(plane));
> >> >>  }
> >> >>
> >> >> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
> >> >> +{
> >> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
> >> >> +		return true;
> >> >> +
> >> >> +	switch (format) {
> >> >> +	case DRM_FORMAT_C8:
> >> >> +	case DRM_FORMAT_RGB565:
> >> >> +	case DRM_FORMAT_XRGB1555:
> >> >> +	case DRM_FORMAT_XRGB8888:
> >> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> >> +	default:
> >> >> +		return false;
> >> >> +	}
> >> >> +}
> >> >> +
> >> >> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
> >> >> +{
> >> >> +	switch (format) {
> >> >> +	case DRM_FORMAT_C8:
> >> >> +	case DRM_FORMAT_RGB565:
> >> >> +	case DRM_FORMAT_XRGB8888:
> >> >> +	case DRM_FORMAT_XBGR8888:
> >> >> +	case DRM_FORMAT_XRGB2101010:
> >> >> +	case DRM_FORMAT_XBGR2101010:
> >> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> >> +	default:
> >> >> +		return false;
> >> >> +	}
> >> >> +}
> >> >
> >> >Hmm. There should be no format vs. tiling restrictions on these
> >> >platforms, so presumably a simple "return true" should cover it all.
> >> >That does perhaps remove the usefulness of these functions for
> >> >verifying that the format or modifier is supported at all
> >>
> >> One of the reasons for changing to this current format-modifier lookup at all
> >> was Kristian's approach was considered fragile. If for whatever reason formats
> >> are added, or removed, we'll catch it here. Also, it maybe let's us do something
> >> on cursor plane at some point (I don't actually know). So yeah, we can return
> >> true, but I like that it's spelled out explicitly. Makes it easy to compare it
> >> to the docs as well to make sure our code is correct.
> >>
> >> The benefit is of course I can combine i965_mod_supported() with
> >> i8xx_mod_supported()
> >>
> >> I'm honestly fine with changing it as well, I just don't see a huge reason to
> >> change it since I've already typed it up. I'll leave it to you.
> >
> >Feel free to keep it. We can always change it later if it becomes too much
> >work to maintain the duplicated format lists (the function and the array).
> >Not that I really expect these lists to be all that volatile.
> >
> >>
> >> [ ] Yes, change it.
> >> [ ] No, leave it.
> >>
> >> >but I've been thinking that addfb should perhaps just iterate through the
> >> >format and modifier lists for every plane. Would avoid having to effectively
> >> >maintain the same lists in multiple places.
> >> >
> >>
> >> I don't quite follow this. Can you elaborate?
> >
> >I was just thinking that instead of addfb passing in an unverified format
> >to the driver's .fb_create() hook, it could first go through the format
> >lists of each plane, and make sure at least one of them supports the
> >requested format. That way we could eliminate that fragile pixel_format
> >switch statement from intel_framebuffer_init().
> >
> >But if you plan on making the .format_mod_supported() hooks 100%
> >strict, then we could use that instead. Would avoid having to walk
> >the format lists of every plane at least.
> >
> 
> Let's keep it the way things are for now, mostly because I'm lazy and this
> works.
> 
> >>
> >> >> +
> >> >> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
> >> >> +{
> >> >> +	switch (format) {
> >> >> +	case DRM_FORMAT_C8:
> >> >> +	case DRM_FORMAT_RGB565:
> >> >> +	case DRM_FORMAT_XRGB8888:
> >> >> +	case DRM_FORMAT_XBGR8888:
> >> >> +	case DRM_FORMAT_ARGB8888:
> >> >> +	case DRM_FORMAT_ABGR8888:
> >> >> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
> >> >> +			modifier == I915_FORMAT_MOD_X_TILED;
> >> >> +	case DRM_FORMAT_XRGB2101010:
> >> >> +	case DRM_FORMAT_XBGR2101010:
> >> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
> >> >> +	case DRM_FORMAT_YUYV:
> >> >> +	case DRM_FORMAT_YVYU:
> >> >> +	case DRM_FORMAT_UYVY:
> >> >> +	case DRM_FORMAT_VYUY:
> >> >
> >> >IIRC on SKL the only restrictions should be that CCS modifiers are
> >> >limited to 8:8:8:8 formats only. Other modifiers should work
> >> >with any format.
> >> >
> >>
> >> This restriction was copied from Kristian's patch. I just checked the docs and
> >> you are correct. So this needs Yf modifier too. (Aside from CCS, rotation is the
> >> one case: x-tiled 1010102 isn't supported).
> >
> >I can't see any extra restrictions for 10bpc formats.
> >
> >The only exception I see for 0/180 degree rotation is FP16 not being
> >supported with Yf. And since we don't actually expose FP16 we don't have
> >to worry about it. So apart from the CCS+8:8:8:8 cases all other
> >format+modifier combos should be perfectly fine AFAICS.
> >
> >My information was gleaned from the "plane capability" table in the
> >spec, but I wasn't able to immediately spot any additional restriction
> >in the PLANE_CTL register description either.
> >
> 
> Sorry for making you verify that, I think you are correct and I'm misreading the
> table. I was just looking at the specific columns: Linear and X-tiled 90/270
> rotation aren't supported with 1010102, but they aren't supported with any other
> surface format either.
> 
> However, looking again now, it looks like DRM_FORMAT_C8 doesn't support Yf.

Hmm. Indeed. That might be related to 
https://lists.freedesktop.org/archives/intel-gfx/2017-January/116027.html

My observation on actual hardware was that Yf tile width didn't match
what we were expecting with 8bpp and 64bpp formats. It did actually work
otherwise though. Possibly someone else noticed the same problem and
"removed" Yf support for these formats. Either that or it was like this
all the time and we just didn't notice. Although I'm still not 100% sure
what the Yf tile width should be since the spec is superbly confusing on
this topic.

If we reject Yf on 8bpp, then I can probably just drop that patch of
mine, and someone will get to revisit it when/if we officially get
8bpp/64bpp Yf support.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 19:27                 ` Daniel Stone
@ 2017-01-13  9:37                   ` Ville Syrjälä
  2017-01-13  9:45                     ` Daniel Stone
  0 siblings, 1 reply; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-13  9:37 UTC (permalink / raw)
  To: Daniel Stone; +Cc: Intel GFX, Ben Widawsky, DRI Development

On Thu, Jan 12, 2017 at 07:27:03PM +0000, Daniel Stone wrote:
> Hi,
> 
> On 12 January 2017 at 18:11, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
> > On Thu, Jan 12, 2017 at 05:50:15PM +0000, Daniel Stone wrote:
> >> struct drm_plane {
> >>     struct {
> >>         uint32_t format;
> >>         uint64_t modifiers[];
> >>     } formats[];
> >> }
> >
> > Flipping formats[] vs. modifiers[] here would seem like it should make
> > this easier with the proposed kernel API. And if the kernel will also
> > uarantee that multiple instances of the same modifier must be returned
> > contiguously, then it should be even easier.
> >
> > Oh and flipping formats[] and modifiers[] should also save a quite a
> > bit of space since each format takes twice as much space as each
> > modifier. But I suppose that might come at a runtime cost if you have
> > to look for a specific format in each modifier's format list instead
> > of having to look at just the modifier list of a specific format. So
> > I suppose not flipping might be better after all, which I guess would
> > complicate populating the infromation somewhat.
> >
> > Anyways, that's all a bit unrelated to the matter at hand, so I'll stop
> > now and just state that I don't mind having an explicit offset if
> > people really want it.
> 
> It would make sense, but then gbm_surface_create_with_modifiers takes
> a fixed pixel format and a list of acceptable modifiers (which to me
> seems like the right way around as an API), so whenever I was creating
> a surface, I'd have to walk through and create a new list, flipped
> back the other way.

Yeah, for that your original order makes more sense, even if it
potentially uses more memory.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-13  9:37                   ` [Intel-gfx] " Ville Syrjälä
@ 2017-01-13  9:45                     ` Daniel Stone
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Stone @ 2017-01-13  9:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel GFX, Ben Widawsky, DRI Development

Hey,

On 13 January 2017 at 09:37, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> On Thu, Jan 12, 2017 at 07:27:03PM +0000, Daniel Stone wrote:
>> It would make sense, but then gbm_surface_create_with_modifiers takes
>> a fixed pixel format and a list of acceptable modifiers (which to me
>> seems like the right way around as an API), so whenever I was creating
>> a surface, I'd have to walk through and create a new list, flipped
>> back the other way.
>
> Yeah, for that your original order makes more sense, even if it
> potentially uses more memory.

Given the size of framebuffers, I'm really not concerned by the
in-memory size of a format list. :)

Cheers,
Daniel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/3] [v2] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
  2017-01-12  1:43   ` [Intel-gfx] " Rob Clark
  2017-01-12 10:23   ` [Intel-gfx] " Ville Syrjälä
@ 2017-01-25  5:20   ` Ben Widawsky
  2017-01-25 15:28     ` Ville Syrjälä
  2017-01-26 23:34     ` [PATCH 1/3] [v3] " Ben Widawsky
  2 siblings, 2 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-25  5:20 UTC (permalink / raw)
  To: Intel GFX, DRI Development; +Cc: Ben Widawsky, Kristian H. Kristensen

Originally based off of a patch by Kristian.

This new ioctl extends DRM_IOCTL_MODE_GETPLANE, by returning information
about the modifiers that will work with each format.

It's modified from Kristian's patch in that the modifiers and formats
are setup by the driver, and then a callback is used to create the
format list. The LOC was enough difference that I don't think it made
sense to leave his authorship, but the new UABI was primarily his idea.

Additionally, I hit a couple of drivers which Kristian missed updating.

It also contains a change requested by Daniel to make the modifiers
array a sentinel based structure instead of a sized one. Upon discussion
on IRC, it was determined that having an invalid modifier might make
sense in general as well.

v2:
  - Make formats uint32_t, and use an offset, see the comment in the
  patch. Add a WARN_ON and early bail for when there are more than 32
  formats. (Rob)
  - Name format_modifiers annotation properly (Ville)
  - Remove DRM_DEBUG_KMS (Ville)
  - make flags come before count in struct (Ville)

Cc: Rob Clark <robdclark@gmail.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Stone <daniel@fooishbar.org>
Cc: "Kristian H. Kristensen" <hoegsberg@gmail.com>
References: https://patchwork.kernel.org/patch/9482393/
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/arc/arcpgu_crtc.c               |  1 +
 drivers/gpu/drm/arm/hdlcd_crtc.c                |  1 +
 drivers/gpu/drm/arm/malidp_planes.c             |  2 +-
 drivers/gpu/drm/armada/armada_crtc.c            |  1 +
 drivers/gpu/drm/armada/armada_overlay.c         |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |  4 +-
 drivers/gpu/drm/drm_ioctl.c                     |  2 +-
 drivers/gpu/drm/drm_modeset_helper.c            |  1 +
 drivers/gpu/drm/drm_plane.c                     | 65 ++++++++++++++++++++++++-
 drivers/gpu/drm/drm_simple_kms_helper.c         |  3 ++
 drivers/gpu/drm/exynos/exynos_drm_plane.c       |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |  1 +
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c            |  7 ++-
 drivers/gpu/drm/i915/intel_sprite.c             |  4 +-
 drivers/gpu/drm/imx/ipuv3-plane.c               |  4 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c        |  2 +-
 drivers/gpu/drm/meson/meson_plane.c             |  1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |  2 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.c               |  2 +-
 drivers/gpu/drm/nouveau/nv50_display.c          |  5 +-
 drivers/gpu/drm/omapdrm/omap_plane.c            |  3 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +-
 drivers/gpu/drm/sti/sti_cursor.c                |  1 +
 drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c             |  1 +
 drivers/gpu/drm/tegra/dc.c                      | 12 ++---
 drivers/gpu/drm/vc4/vc4_plane.c                 |  2 +-
 drivers/gpu/drm/virtio/virtgpu_plane.c          |  2 +-
 drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
 include/drm/drm_plane.h                         | 21 +++++++-
 include/drm/drm_simple_kms_helper.h             |  1 +
 include/uapi/drm/drm.h                          |  1 +
 include/uapi/drm/drm_fourcc.h                   | 11 +++++
 include/uapi/drm/drm_mode.h                     | 36 ++++++++++++++
 40 files changed, 189 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
index ad9a95916f1f..cd8a24c7c67d 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -218,6 +218,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 20ebfb4fbdfa..89fded880807 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -283,6 +283,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &hdlcd_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		devm_kfree(drm->dev, plane);
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index eff2fe47e26a..94dbcbc9ad8f 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -283,7 +283,7 @@ int malidp_de_planes_init(struct drm_device *drm)
 					DRM_PLANE_TYPE_OVERLAY;
 		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
 					       &malidp_de_plane_funcs, formats,
-					       n, plane_type, NULL);
+					       n, NULL, plane_type, NULL);
 		if (ret < 0)
 			goto cleanup;
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e62ee4498ce4..39330145ba2a 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1250,6 +1250,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 				       &armada_primary_plane_funcs,
 				       armada_primary_formats,
 				       ARRAY_SIZE(armada_primary_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 34cb73d0db77..6a1ca8aa8e16 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -458,6 +458,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 				       &armada_ovl_plane_funcs,
 				       armada_ovl_formats,
 				       ARRAY_SIZE(armada_ovl_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (ret) {
 		kfree(dplane);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index bd2791c4b002..f12cec0bc58c 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -1038,7 +1038,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, &plane->base, 0,
 				       &layer_plane_funcs,
 				       desc->formats->formats,
-				       desc->formats->nformats, type, NULL);
+				       desc->formats->nformats,
+				       NULL,
+				       type, NULL);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a7c61c23685a..c820d99d9231 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -614,7 +614,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE2, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index 2b33825f2f93..9cb1eede0b4d 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
 				       &drm_primary_helper_funcs,
 				       safe_modeset_formats,
 				       ARRAY_SIZE(safe_modeset_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 7b7275f0c2df..188e7428b807 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
  * @funcs: callbacks for the new plane
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of struct drm_format modifiers terminated by INVALID
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default name
  *
@@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats, unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...)
 {
 	struct drm_mode_config *config = &dev->mode_config;
+	unsigned int format_modifier_count = 0;
 	int ret;
 
 	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +108,24 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		return -ENOMEM;
 	}
 
+	if (format_modifiers) {
+		const uint64_t *temp_modifiers = format_modifiers;
+		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
+			format_modifier_count++;
+	}
+
+	plane->modifier_count = format_modifier_count;
+	plane->modifiers = kmalloc_array(format_modifier_count,
+					 sizeof(format_modifiers[0]),
+					 GFP_KERNEL);
+
+	if (format_modifier_count && !plane->modifiers) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		kfree(plane->format_types);
+		drm_mode_object_unregister(dev, &plane->base);
+		return -ENOMEM;
+	}
+
 	if (name) {
 		va_list ap;
 
@@ -117,12 +138,15 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 	}
 	if (!plane->name) {
 		kfree(plane->format_types);
+		kfree(plane->modifiers);
 		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
 	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 	plane->format_count = format_count;
+	memcpy(plane->modifiers, format_modifiers,
+	       format_modifier_count * sizeof(format_modifiers[0]));
 	plane->possible_crtcs = possible_crtcs;
 	plane->type = type;
 
@@ -205,7 +229,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-					formats, format_count, type, NULL);
+					formats, format_count,
+					NULL, type, NULL);
 }
 EXPORT_SYMBOL(drm_plane_init);
 
@@ -224,6 +249,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
 	drm_modeset_lock_fini(&plane->mutex);
 
 	kfree(plane->format_types);
+	kfree(plane->modifiers);
 	drm_mode_object_unregister(dev, &plane->base);
 
 	BUG_ON(list_empty(&plane->head));
@@ -380,12 +406,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
 int drm_mode_getplane(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv)
 {
-	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_get_plane2 *plane_resp = data;
 	struct drm_plane *plane;
 	uint32_t __user *format_ptr;
+	struct drm_format_modifier __user *modifier_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
+	if (plane_resp->flags)
+		return -EINVAL;
 
 	plane = drm_plane_find(dev, plane_resp->plane_id);
 	if (!plane)
@@ -426,6 +455,38 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 	}
 	plane_resp->count_format_types = plane->format_count;
 
+	if (plane->modifier_count &&
+	    plane_resp->count_format_modifiers >= plane->modifier_count) {
+		struct drm_format_modifier mod;
+		int i;
+
+		modifier_ptr = (struct drm_format_modifier __user *)
+			(unsigned long)plane_resp->format_modifier_ptr;
+
+		/* Build the mask for each modifier */
+		for (i = 0; i < plane->modifier_count; i++) {
+			int j;
+			mod.modifier = plane->modifiers[i];
+			for (j = 0; j < plane->format_count; j++) {
+				if (plane->funcs->format_mod_supported &&
+				    plane->funcs->format_mod_supported(plane,
+								       plane->format_types[j],
+								       plane->modifiers[i])) {
+					if (WARN_ON(j > 31))
+						break;
+					mod.formats |= 1 << j;
+				}
+			}
+
+			if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
+				return -EFAULT;
+
+			modifier_ptr++;
+		}
+	}
+
+	plane_resp->count_format_modifiers = plane->modifier_count;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 35c5d99296b9..6c099694fccb 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -193,6 +193,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
  * @funcs: callbacks for the display pipe (optional)
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of formats modifiers
  * @connector: connector to attach and register (optional)
  *
  * Sets up a display pipeline which consist of a really simple
@@ -213,6 +214,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &pipe->encoder;
@@ -227,6 +229,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0,
 				       &drm_simple_kms_plane_funcs,
 				       formats, format_count,
+				       format_modifiers,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c2f17f30afab..75d4928dd196 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -284,7 +284,7 @@ int exynos_plane_init(struct drm_device *dev,
 				       &exynos_plane_funcs,
 				       config->pixel_formats,
 				       config->num_pixel_formats,
-				       config->type, NULL);
+				       NULL, config->type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index 0a20723aa6e1..9554b245746e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -224,7 +224,7 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 				       &fsl_dcu_drm_plane_funcs,
 				       fsl_dcu_drm_plane_formats,
 				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
 		primary = NULL;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index c655883d3613..919cc807809f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -181,6 +181,7 @@ static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
 	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
 				       channel_formats1,
 				       ARRAY_SIZE(channel_formats1),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY,
 				       NULL);
 	if (ret) {
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index 307d460ab684..b433b8e7c9cd 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -911,7 +911,7 @@ static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane,
 		return ret;
 
 	ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs,
-				       fmts, fmts_cnt, type, NULL);
+				       fmts, fmts_cnt, NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
 		return ret;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b547332eeda1..8715b1083d1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15303,6 +15303,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 					      src_x, src_y, src_w, src_h);
 }
 
+
+
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
 	.update_plane = intel_legacy_cursor_update,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -15387,18 +15389,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
 	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
@@ -15563,7 +15568,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 				       0, &intel_cursor_plane_funcs,
 				       intel_cursor_formats,
 				       ARRAY_SIZE(intel_cursor_formats),
-				       DRM_PLANE_TYPE_CURSOR,
+				       NULL, DRM_PLANE_TYPE_CURSOR,
 				       "cursor %c", pipe_name(pipe));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 063a994815d0..1c2f26d86f76 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1127,13 +1127,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 8b5294d47cee..ef9e11b98b3c 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -496,8 +496,8 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
 
 	ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
 				       &ipu_plane_funcs, ipu_plane_formats,
-				       ARRAY_SIZE(ipu_plane_formats), type,
-				       NULL);
+				       ARRAY_SIZE(ipu_plane_formats),
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("failed to initialize plane\n");
 		kfree(ipu_plane);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index e405e89ed5e5..bec6d14dd070 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -173,7 +173,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	err = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &mtk_plane_funcs, formats,
-				       ARRAY_SIZE(formats), type, NULL);
+				       ARRAY_SIZE(formats), NULL, type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 642b2fab42ff..13c7c2c1d4cc 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -220,6 +220,7 @@ int meson_plane_create(struct meson_drm *priv)
 				 &meson_plane_funcs,
 				 supported_drm_formats,
 				 ARRAY_SIZE(supported_drm_formats),
+				 NULL,
 				 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
 
 	drm_plane_helper_add(plane, &meson_plane_helper_funcs);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 53619d07677e..8f3417e45d4e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -398,7 +398,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
 				 mdp4_plane->formats, mdp4_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 75247ea4335b..c2068c30ca73 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -882,7 +882,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 955441f71500..f29d463e03a4 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -186,7 +186,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	}
 
 	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
-			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, 0,
 			&mxsfb->connector);
 	if (ret < 0) {
 		dev_err(drm->dev, "Cannot setup simple display pipe\n");
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index cb85cb72dc1c..cf5ed98caed4 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1079,8 +1079,9 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
 	wndw->func = func;
 	wndw->dmac = dmac;
 
-	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
-				       nformat, type, "%s-%d", name, index);
+	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw,
+				       format, nformat, NULL,
+				       type, "%s-%d", name, index);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 82b2c23d6769..b4a575cf7e71 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -383,7 +383,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &omap_plane_funcs, omap_plane->formats,
-				       omap_plane->nformats, type, NULL);
+				       omap_plane->nformats,
+				       NULL, type, NULL);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index dcde6288da6c..2b02eccbfb70 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -743,8 +743,8 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
 
 		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
 					       &rcar_du_plane_funcs, formats,
-					       ARRAY_SIZE(formats), type,
-					       NULL);
+					       ARRAY_SIZE(formats),
+					       NULL, type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index b5bfbe50bd87..744be029436b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -364,8 +364,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 					       1 << vsp->index,
 					       &rcar_du_vsp_plane_funcs,
 					       formats_kms,
-					       ARRAY_SIZE(formats_kms), type,
-					       NULL);
+					       ARRAY_SIZE(formats_kms),
+					       NULL,
+					       type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fb5f001f51c3..826b376114f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1221,7 +1221,7 @@ static int vop_create_crtc(struct vop *vop)
 					       0, &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
 				      ret);
@@ -1260,7 +1260,7 @@ static int vop_create_crtc(struct vop *vop)
 					       &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
 				      ret);
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index cca75bddb9ad..f61808b419a5 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -393,6 +393,7 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
 				       &sti_cursor_plane_helpers_funcs,
 				       cursor_supported_formats,
 				       ARRAY_SIZE(cursor_supported_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 877d053d86f4..6bf1a592cee4 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -921,7 +921,7 @@ struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
 				       &sti_gdp_plane_helpers_funcs,
 				       gdp_supported_formats,
 				       ARRAY_SIZE(gdp_supported_formats),
-				       type, NULL);
+				       NULL, type, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		goto err;
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index becf10d255c4..911e8f0f69a6 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1277,7 +1277,7 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
 				       &sti_hqvdp_plane_helpers_funcs,
 				       hqvdp_supported_formats,
 				       ARRAY_SIZE(hqvdp_supported_formats),
-				       DRM_PLANE_TYPE_OVERLAY, NULL);
+				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 5d53c977bca5..827f45364654 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -117,6 +117,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
 				       &sun4i_backend_layer_funcs,
 				       plane->formats, plane->nformats,
+				       NULL,
 				       plane->type, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 7561a95a54e3..9ddea84208c4 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -655,8 +655,8 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
 				       &tegra_primary_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_PRIMARY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -821,8 +821,8 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_cursor_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_CURSOR,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -883,8 +883,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_overlay_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_OVERLAY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 110d1518f5d5..487bb40e0e4e 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -861,7 +861,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0xff,
 				       &vc4_plane_funcs,
 				       formats, num_formats,
-				       type, NULL);
+				       NULL, type, NULL);
 
 	drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 11288ffa4af6..00f368cde0b8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -225,7 +225,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
 	ret = drm_universal_plane_init(dev, plane, 1 << index,
 				       &virtio_gpu_plane_funcs,
 				       formats, nformats,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret)
 		goto err_plane_init;
 
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index b634b090cdc1..c57d4fe5da18 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -287,7 +287,7 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
 
 	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
 				       &zx_plane_funcs, formats, format_count,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
 		return ERR_PTR(ret);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index e049bc52fb07..108a955438e5 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -389,6 +389,20 @@ struct drm_plane_funcs {
 	 */
 	void (*atomic_print_state)(struct drm_printer *p,
 				   const struct drm_plane_state *state);
+
+	/**
+	 * @format_mod_supported:
+	 *
+	 * This optional hook is used for the DRM to determine if the given
+	 * format/modifier combination is valid for the plane. This allows the
+	 * DRM to generate the correct format bitmask (which formats apply to
+	 * which modifier).
+	 *
+	 * True if the given modifier is valid for that format on the plane.
+	 * False otherwise.
+	 */
+	bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,
+				     uint64_t modifier);
 };
 
 /**
@@ -483,6 +497,10 @@ struct drm_plane {
 	unsigned int format_count;
 	bool format_default;
 
+	uint32_t *formats;
+	uint64_t *modifiers;
+	unsigned int modifier_count;
+
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 
@@ -510,13 +528,14 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-extern __printf(8, 9)
+extern __printf(9, 10)
 int drm_universal_plane_init(struct drm_device *dev,
 			     struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats,
 			     unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...);
 extern int drm_plane_init(struct drm_device *dev,
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index fe8c4ba905ac..059cd592a127 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -118,6 +118,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector);
 
 #endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b2c52843bc70..487e0f17113f 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -805,6 +805,7 @@ extern "C" {
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_GETPLANE2	DRM_IOWR(0xB6, struct drm_mode_get_plane2)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 4581e3d41e5c..5859014d93c7 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -162,6 +162,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
 /* add more to the end as needed */
 
+#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
+
 #define fourcc_mod_code(vendor, val) \
 	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
 
@@ -174,6 +176,15 @@ extern "C" {
  */
 
 /*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate list, or to initialize a
+ * variable with an invalid modifier. It might also be used to report an error
+ * back to userspace for certain APIs.
+ */
+#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
+/*
  * Linear Layout
  *
  * Just plain linear layout. Note that this is different from no specifying any
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ce7efe2e8a5e..63932b28ddd0 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -209,6 +209,42 @@ struct drm_mode_get_plane {
 	__u64 format_type_ptr;
 };
 
+struct drm_format_modifier {
+	/* Bitmask of formats in get_plane format list this info applies to. The
+	 * offset allows a sliding window of which 32 formats (bits).
+	 *
+	 * For example, if the formats grew to 128, and the last formats were
+	 * supported with the modifier:
+	 *
+	 * 0xFFFFFFFF 00000000 00000000 00000000
+	 *          ^
+	 *          |__offset = 96, formats = 0xffffffff
+	 */
+	uint32_t formats;
+	uint32_t offset;
+
+	/* This modifier can be used with the format for this plane. */
+	uint64_t modifier;
+};
+
+struct drm_mode_get_plane2 {
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+	__u64 format_type_ptr;
+
+	/* New in v2 */
+	__u32 flags;
+	__u32 count_format_modifiers;
+	__u64 format_modifier_ptr;
+};
+
 struct drm_mode_get_plane_res {
 	__u64 plane_id_ptr;
 	__u32 count_planes;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev2)
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
                   ` (3 preceding siblings ...)
  2017-01-12  1:01 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation Patchwork
@ 2017-01-25  6:32 ` Patchwork
  2017-01-27  1:02 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev3) Patchwork
  5 siblings, 0 replies; 28+ messages in thread
From: Patchwork @ 2017-01-25  6:32 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx

== Series Details ==

Series: GET_PLANE2 w/ i915 implementation (rev2)
URL   : https://patchwork.freedesktop.org/series/17873/
State : failure

== Summary ==

  LD      drivers/usb/storage/usb-storage.o
  LD      drivers/usb/storage/built-in.o
  LD      drivers/acpi/built-in.o
  LD      net/ipv6/built-in.o
  LD [M]  drivers/misc/mei/mei-me.o
  LD      drivers/misc/built-in.o
  LD      drivers/pci/pcie/pcieportdrv.o
  LD      drivers/tty/serial/8250/8250.o
  LD [M]  drivers/mmc/core/mmc_block.o
  LD      drivers/mmc/built-in.o
  LD      drivers/gpu/drm/drm.o
  LD [M]  drivers/usb/serial/usbserial.o
  LD      drivers/scsi/scsi_mod.o
  LD [M]  drivers/net/ethernet/broadcom/genet/genet.o
  LD [M]  sound/pci/hda/snd-hda-codec-generic.o
  LD      drivers/pci/pcie/aer/aerdriver.o
  LD      drivers/pci/pcie/aer/built-in.o
  LD      sound/pci/built-in.o
  LD      drivers/pci/pcie/built-in.o
  LD      drivers/usb/gadget/udc/udc-core.o
  LD      drivers/usb/gadget/udc/built-in.o
  LD      drivers/iommu/built-in.o
  LD      drivers/thermal/thermal_sys.o
  LD      drivers/thermal/built-in.o
drivers/gpu/drm/i915/intel_display.c:100:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_display.c:101:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
  LD      sound/built-in.o
  LD      drivers/usb/gadget/libcomposite.o
  LD      drivers/usb/gadget/built-in.o
drivers/gpu/drm/i915/intel_sprite.c:1043:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_sprite.c:1044:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
  LD      drivers/video/fbdev/core/fb.o
  LD      drivers/video/fbdev/core/built-in.o
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_sprite.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_sprite.o] Error 1
make[4]: *** Waiting for unfinished jobs....
drivers/gpu/drm/i915/intel_display.c: In function ‘skl_mod_supported’:
drivers/gpu/drm/i915/intel_display.c:15053:20: error: comparison between pointer and integer [-Werror]
   return  modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
                    ^
drivers/gpu/drm/i915/intel_display.c:15054:13: error: comparison between pointer and integer [-Werror]
    modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
             ^
cc1: all warnings being treated as errors
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_display.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_display.o] Error 1
  LD      drivers/spi/built-in.o
  LD      drivers/tty/serial/8250/8250_base.o
  LD      drivers/video/fbdev/built-in.o
  LD      drivers/tty/serial/8250/built-in.o
  LD [M]  drivers/net/ethernet/intel/igbvf/igbvf.o
  LD      drivers/tty/serial/built-in.o
  LD      net/ipv4/built-in.o
  LD      drivers/scsi/sd_mod.o
  LD      drivers/scsi/built-in.o
  LD      fs/btrfs/btrfs.o
  LD      drivers/pci/built-in.o
  LD      fs/btrfs/built-in.o
  LD [M]  drivers/net/ethernet/intel/e1000/e1000.o
  LD      drivers/video/console/built-in.o
  LD      drivers/video/built-in.o
  CC      arch/x86/kernel/cpu/capflags.o
  LD      arch/x86/kernel/cpu/built-in.o
  LD      arch/x86/kernel/built-in.o
  LD      drivers/usb/core/usbcore.o
  LD      drivers/usb/core/built-in.o
  LD      drivers/usb/host/xhci-hcd.o
  LD      arch/x86/built-in.o
  LD      drivers/tty/vt/built-in.o
  LD      drivers/tty/built-in.o
  LD      fs/ext4/ext4.o
  LD      drivers/usb/host/built-in.o
  LD      drivers/usb/built-in.o
  LD      fs/ext4/built-in.o
  LD      net/core/built-in.o
  LD      fs/built-in.o
  LD      net/built-in.o
  LD [M]  drivers/net/ethernet/intel/igb/igb.o
  LD      drivers/md/md-mod.o
  LD      drivers/md/built-in.o
  LD [M]  drivers/net/ethernet/intel/e1000e/e1000e.o
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
make[1]: *** Waiting for unfinished jobs....
  LD      drivers/net/ethernet/built-in.o
  LD      drivers/net/built-in.o
Makefile:988: recipe for target 'drivers' failed
make: *** [drivers] Error 2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 1/3] [v2] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-25  5:20   ` [PATCH 1/3] [v2] " Ben Widawsky
@ 2017-01-25 15:28     ` Ville Syrjälä
  2017-01-26 23:34     ` [PATCH 1/3] [v3] " Ben Widawsky
  1 sibling, 0 replies; 28+ messages in thread
From: Ville Syrjälä @ 2017-01-25 15:28 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Kristian H. Kristensen, DRI Development

On Tue, Jan 24, 2017 at 09:20:49PM -0800, Ben Widawsky wrote:
> Originally based off of a patch by Kristian.
> 
> This new ioctl extends DRM_IOCTL_MODE_GETPLANE, by returning information
> about the modifiers that will work with each format.
> 
> It's modified from Kristian's patch in that the modifiers and formats
> are setup by the driver, and then a callback is used to create the
> format list. The LOC was enough difference that I don't think it made
> sense to leave his authorship, but the new UABI was primarily his idea.
> 
> Additionally, I hit a couple of drivers which Kristian missed updating.
> 
> It also contains a change requested by Daniel to make the modifiers
> array a sentinel based structure instead of a sized one. Upon discussion
> on IRC, it was determined that having an invalid modifier might make
> sense in general as well.
> 
> v2:
>   - Make formats uint32_t, and use an offset, see the comment in the
>   patch. Add a WARN_ON and early bail for when there are more than 32
>   formats. (Rob)
>   - Name format_modifiers annotation properly (Ville)
>   - Remove DRM_DEBUG_KMS (Ville)
>   - make flags come before count in struct (Ville)
> 
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Stone <daniel@fooishbar.org>
> Cc: "Kristian H. Kristensen" <hoegsberg@gmail.com>
> References: https://patchwork.kernel.org/patch/9482393/
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/arc/arcpgu_crtc.c               |  1 +
>  drivers/gpu/drm/arm/hdlcd_crtc.c                |  1 +
>  drivers/gpu/drm/arm/malidp_planes.c             |  2 +-
>  drivers/gpu/drm/armada/armada_crtc.c            |  1 +
>  drivers/gpu/drm/armada/armada_overlay.c         |  1 +
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |  4 +-
>  drivers/gpu/drm/drm_ioctl.c                     |  2 +-
>  drivers/gpu/drm/drm_modeset_helper.c            |  1 +
>  drivers/gpu/drm/drm_plane.c                     | 65 ++++++++++++++++++++++++-
>  drivers/gpu/drm/drm_simple_kms_helper.c         |  3 ++
>  drivers/gpu/drm/exynos/exynos_drm_plane.c       |  2 +-
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |  2 +-
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |  1 +
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  2 +-
>  drivers/gpu/drm/i915/intel_display.c            |  7 ++-
>  drivers/gpu/drm/i915/intel_sprite.c             |  4 +-
>  drivers/gpu/drm/imx/ipuv3-plane.c               |  4 +-
>  drivers/gpu/drm/mediatek/mtk_drm_plane.c        |  2 +-
>  drivers/gpu/drm/meson/meson_plane.c             |  1 +
>  drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |  2 +-
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |  2 +-
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c               |  2 +-
>  drivers/gpu/drm/nouveau/nv50_display.c          |  5 +-
>  drivers/gpu/drm/omapdrm/omap_plane.c            |  3 +-
>  drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +-
>  drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  5 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +-
>  drivers/gpu/drm/sti/sti_cursor.c                |  1 +
>  drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
>  drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
>  drivers/gpu/drm/sun4i/sun4i_layer.c             |  1 +
>  drivers/gpu/drm/tegra/dc.c                      | 12 ++---
>  drivers/gpu/drm/vc4/vc4_plane.c                 |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_plane.c          |  2 +-
>  drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
>  include/drm/drm_plane.h                         | 21 +++++++-
>  include/drm/drm_simple_kms_helper.h             |  1 +
>  include/uapi/drm/drm.h                          |  1 +
>  include/uapi/drm/drm_fourcc.h                   | 11 +++++
>  include/uapi/drm/drm_mode.h                     | 36 ++++++++++++++
>  40 files changed, 189 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> index ad9a95916f1f..cd8a24c7c67d 100644
> --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> @@ -218,6 +218,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
>  
>  	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
>  				       formats, ARRAY_SIZE(formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret)
>  		return ERR_PTR(ret);
> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> index 20ebfb4fbdfa..89fded880807 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -283,6 +283,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
>  
>  	ret = drm_universal_plane_init(drm, plane, 0xff, &hdlcd_plane_funcs,
>  				       formats, ARRAY_SIZE(formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		devm_kfree(drm->dev, plane);
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index eff2fe47e26a..94dbcbc9ad8f 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -283,7 +283,7 @@ int malidp_de_planes_init(struct drm_device *drm)
>  					DRM_PLANE_TYPE_OVERLAY;
>  		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
>  					       &malidp_de_plane_funcs, formats,
> -					       n, plane_type, NULL);
> +					       n, NULL, plane_type, NULL);
>  		if (ret < 0)
>  			goto cleanup;
>  
> diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
> index e62ee4498ce4..39330145ba2a 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -1250,6 +1250,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
>  				       &armada_primary_plane_funcs,
>  				       armada_primary_formats,
>  				       ARRAY_SIZE(armada_primary_formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		kfree(primary);
> diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
> index 34cb73d0db77..6a1ca8aa8e16 100644
> --- a/drivers/gpu/drm/armada/armada_overlay.c
> +++ b/drivers/gpu/drm/armada/armada_overlay.c
> @@ -458,6 +458,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
>  				       &armada_ovl_plane_funcs,
>  				       armada_ovl_formats,
>  				       ARRAY_SIZE(armada_ovl_formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_OVERLAY, NULL);
>  	if (ret) {
>  		kfree(dplane);
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> index bd2791c4b002..f12cec0bc58c 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> @@ -1038,7 +1038,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
>  	ret = drm_universal_plane_init(dev, &plane->base, 0,
>  				       &layer_plane_funcs,
>  				       desc->formats->formats,
> -				       desc->formats->nformats, type, NULL);
> +				       desc->formats->nformats,
> +				       NULL,
> +				       type, NULL);
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index a7c61c23685a..c820d99d9231 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -614,7 +614,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE2, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
> diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
> index 2b33825f2f93..9cb1eede0b4d 100644
> --- a/drivers/gpu/drm/drm_modeset_helper.c
> +++ b/drivers/gpu/drm/drm_modeset_helper.c
> @@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
>  				       &drm_primary_helper_funcs,
>  				       safe_modeset_formats,
>  				       ARRAY_SIZE(safe_modeset_formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		kfree(primary);
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index 7b7275f0c2df..188e7428b807 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
>   * @funcs: callbacks for the new plane
>   * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
> + * @format_modifiers: array of struct drm_format modifiers terminated by INVALID
>   * @type: type of plane (overlay, primary, cursor)
>   * @name: printf style format string for the plane name, or NULL for default name
>   *
> @@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  			     uint32_t possible_crtcs,
>  			     const struct drm_plane_funcs *funcs,
>  			     const uint32_t *formats, unsigned int format_count,
> +			     const uint64_t *format_modifiers,
>  			     enum drm_plane_type type,
>  			     const char *name, ...)
>  {
>  	struct drm_mode_config *config = &dev->mode_config;
> +	unsigned int format_modifier_count = 0;
>  	int ret;
>  
>  	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
> @@ -105,6 +108,24 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  		return -ENOMEM;
>  	}
>  
> +	if (format_modifiers) {
> +		const uint64_t *temp_modifiers = format_modifiers;
> +		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
> +			format_modifier_count++;
> +	}
> +
> +	plane->modifier_count = format_modifier_count;
> +	plane->modifiers = kmalloc_array(format_modifier_count,
> +					 sizeof(format_modifiers[0]),
> +					 GFP_KERNEL);
> +
> +	if (format_modifier_count && !plane->modifiers) {
> +		DRM_DEBUG_KMS("out of memory when allocating plane\n");
> +		kfree(plane->format_types);
> +		drm_mode_object_unregister(dev, &plane->base);
> +		return -ENOMEM;
> +	}
> +
>  	if (name) {
>  		va_list ap;
>  
> @@ -117,12 +138,15 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  	}
>  	if (!plane->name) {
>  		kfree(plane->format_types);
> +		kfree(plane->modifiers);
>  		drm_mode_object_unregister(dev, &plane->base);
>  		return -ENOMEM;
>  	}
>  
>  	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
>  	plane->format_count = format_count;
> +	memcpy(plane->modifiers, format_modifiers,
> +	       format_modifier_count * sizeof(format_modifiers[0]));
>  	plane->possible_crtcs = possible_crtcs;
>  	plane->type = type;
>  
> @@ -205,7 +229,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  
>  	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
>  	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
> -					formats, format_count, type, NULL);
> +					formats, format_count,
> +					NULL, type, NULL);
>  }
>  EXPORT_SYMBOL(drm_plane_init);
>  
> @@ -224,6 +249,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
>  	drm_modeset_lock_fini(&plane->mutex);
>  
>  	kfree(plane->format_types);
> +	kfree(plane->modifiers);
>  	drm_mode_object_unregister(dev, &plane->base);
>  
>  	BUG_ON(list_empty(&plane->head));
> @@ -380,12 +406,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
>  int drm_mode_getplane(struct drm_device *dev, void *data,
>  		      struct drm_file *file_priv)
>  {
> -	struct drm_mode_get_plane *plane_resp = data;
> +	struct drm_mode_get_plane2 *plane_resp = data;
>  	struct drm_plane *plane;
>  	uint32_t __user *format_ptr;
> +	struct drm_format_modifier __user *modifier_ptr;
>  
>  	if (!drm_core_check_feature(dev, DRIVER_MODESET))
>  		return -EINVAL;
> +	if (plane_resp->flags)
> +		return -EINVAL;
>  
>  	plane = drm_plane_find(dev, plane_resp->plane_id);
>  	if (!plane)
> @@ -426,6 +455,38 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
>  	}
>  	plane_resp->count_format_types = plane->format_count;
>  
> +	if (plane->modifier_count &&
> +	    plane_resp->count_format_modifiers >= plane->modifier_count) {
> +		struct drm_format_modifier mod;
> +		int i;
> +
> +		modifier_ptr = (struct drm_format_modifier __user *)
> +			(unsigned long)plane_resp->format_modifier_ptr;
> +
> +		/* Build the mask for each modifier */
> +		for (i = 0; i < plane->modifier_count; i++) {
> +			int j;
> +			mod.modifier = plane->modifiers[i];
> +			for (j = 0; j < plane->format_count; j++) {
> +				if (plane->funcs->format_mod_supported &&
> +				    plane->funcs->format_mod_supported(plane,
> +								       plane->format_types[j],
> +								       plane->modifiers[i])) {
> +					if (WARN_ON(j > 31))
> +						break;

I would prefer to see this handled in the plane init function instead.

> +					mod.formats |= 1 << j;
> +				}
> +			}
> +
> +			if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
> +				return -EFAULT;
> +
> +			modifier_ptr++;
> +		}
> +	}
> +
> +	plane_resp->count_format_modifiers = plane->modifier_count;
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 35c5d99296b9..6c099694fccb 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -193,6 +193,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>   * @funcs: callbacks for the display pipe (optional)
>   * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
> + * @format_modifiers: array of formats modifiers
>   * @connector: connector to attach and register (optional)
>   *
>   * Sets up a display pipeline which consist of a really simple
> @@ -213,6 +214,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
>  			struct drm_simple_display_pipe *pipe,
>  			const struct drm_simple_display_pipe_funcs *funcs,
>  			const uint32_t *formats, unsigned int format_count,
> +			const uint64_t *format_modifiers,
>  			struct drm_connector *connector)
>  {
>  	struct drm_encoder *encoder = &pipe->encoder;
> @@ -227,6 +229,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
>  	ret = drm_universal_plane_init(dev, plane, 0,
>  				       &drm_simple_kms_plane_funcs,
>  				       formats, format_count,
> +				       format_modifiers,
>  				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> index c2f17f30afab..75d4928dd196 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
> @@ -284,7 +284,7 @@ int exynos_plane_init(struct drm_device *dev,
>  				       &exynos_plane_funcs,
>  				       config->pixel_formats,
>  				       config->num_pixel_formats,
> -				       config->type, NULL);
> +				       NULL, config->type, NULL);
>  	if (err) {
>  		DRM_ERROR("failed to initialize plane\n");
>  		return err;
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
> index 0a20723aa6e1..9554b245746e 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
> @@ -224,7 +224,7 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
>  				       &fsl_dcu_drm_plane_funcs,
>  				       fsl_dcu_drm_plane_formats,
>  				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		kfree(primary);
>  		primary = NULL;
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
> index c655883d3613..919cc807809f 100644
> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
> @@ -181,6 +181,7 @@ static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
>  	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
>  				       channel_formats1,
>  				       ARRAY_SIZE(channel_formats1),
> +				       NULL,
>  				       DRM_PLANE_TYPE_PRIMARY,
>  				       NULL);
>  	if (ret) {
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> index 307d460ab684..b433b8e7c9cd 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> @@ -911,7 +911,7 @@ static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane,
>  		return ret;
>  
>  	ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs,
> -				       fmts, fmts_cnt, type, NULL);
> +				       fmts, fmts_cnt, NULL, type, NULL);
>  	if (ret) {
>  		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
>  		return ret;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index b547332eeda1..8715b1083d1d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -15303,6 +15303,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
>  					      src_x, src_y, src_w, src_h);
>  }
>  
> +
> +
>  static const struct drm_plane_funcs intel_cursor_plane_funcs = {
>  	.update_plane = intel_legacy_cursor_update,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -15387,18 +15389,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> +					       NULL,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane 1%c", pipe_name(pipe));
>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> +					       NULL,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "primary %c", pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> +					       NULL,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane %c", plane_name(primary->plane));
>  	if (ret)
> @@ -15563,7 +15568,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  				       0, &intel_cursor_plane_funcs,
>  				       intel_cursor_formats,
>  				       ARRAY_SIZE(intel_cursor_formats),
> -				       DRM_PLANE_TYPE_CURSOR,
> +				       NULL, DRM_PLANE_TYPE_CURSOR,
>  				       "cursor %c", pipe_name(pipe));
>  	if (ret)
>  		goto fail;
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 063a994815d0..1c2f26d86f76 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -1127,13 +1127,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>  					       possible_crtcs, &intel_plane_funcs,
>  					       plane_formats, num_plane_formats,
> -					       DRM_PLANE_TYPE_OVERLAY,
> +					       NULL, DRM_PLANE_TYPE_OVERLAY,
>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>  					       possible_crtcs, &intel_plane_funcs,
>  					       plane_formats, num_plane_formats,
> -					       DRM_PLANE_TYPE_OVERLAY,
> +					       NULL, DRM_PLANE_TYPE_OVERLAY,
>  					       "sprite %c", sprite_name(pipe, plane));
>  	if (ret)
>  		goto fail;
> diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
> index 8b5294d47cee..ef9e11b98b3c 100644
> --- a/drivers/gpu/drm/imx/ipuv3-plane.c
> +++ b/drivers/gpu/drm/imx/ipuv3-plane.c
> @@ -496,8 +496,8 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
>  
>  	ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
>  				       &ipu_plane_funcs, ipu_plane_formats,
> -				       ARRAY_SIZE(ipu_plane_formats), type,
> -				       NULL);
> +				       ARRAY_SIZE(ipu_plane_formats),
> +				       NULL, type, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to initialize plane\n");
>  		kfree(ipu_plane);
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> index e405e89ed5e5..bec6d14dd070 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> @@ -173,7 +173,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  
>  	err = drm_universal_plane_init(dev, plane, possible_crtcs,
>  				       &mtk_plane_funcs, formats,
> -				       ARRAY_SIZE(formats), type, NULL);
> +				       ARRAY_SIZE(formats), NULL, type, NULL);
>  	if (err) {
>  		DRM_ERROR("failed to initialize plane\n");
>  		return err;
> diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
> index 642b2fab42ff..13c7c2c1d4cc 100644
> --- a/drivers/gpu/drm/meson/meson_plane.c
> +++ b/drivers/gpu/drm/meson/meson_plane.c
> @@ -220,6 +220,7 @@ int meson_plane_create(struct meson_drm *priv)
>  				 &meson_plane_funcs,
>  				 supported_drm_formats,
>  				 ARRAY_SIZE(supported_drm_formats),
> +				 NULL,
>  				 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
>  
>  	drm_plane_helper_add(plane, &meson_plane_helper_funcs);
> diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
> index 53619d07677e..8f3417e45d4e 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
> @@ -398,7 +398,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
>  	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
>  	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
>  				 mdp4_plane->formats, mdp4_plane->nformats,
> -				 type, NULL);
> +				 NULL, type, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> index 75247ea4335b..c2068c30ca73 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> @@ -882,7 +882,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
>  	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
>  	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
>  				 mdp5_plane->formats, mdp5_plane->nformats,
> -				 type, NULL);
> +				 NULL, type, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 955441f71500..f29d463e03a4 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -186,7 +186,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
>  	}
>  
>  	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> -			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
> +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, 0,
>  			&mxsfb->connector);
>  	if (ret < 0) {
>  		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index cb85cb72dc1c..cf5ed98caed4 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -1079,8 +1079,9 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
>  	wndw->func = func;
>  	wndw->dmac = dmac;
>  
> -	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
> -				       nformat, type, "%s-%d", name, index);
> +	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw,
> +				       format, nformat, NULL,
> +				       type, "%s-%d", name, index);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
> index 82b2c23d6769..b4a575cf7e71 100644
> --- a/drivers/gpu/drm/omapdrm/omap_plane.c
> +++ b/drivers/gpu/drm/omapdrm/omap_plane.c
> @@ -383,7 +383,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
>  
>  	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
>  				       &omap_plane_funcs, omap_plane->formats,
> -				       omap_plane->nformats, type, NULL);
> +				       omap_plane->nformats,
> +				       NULL, type, NULL);
>  	if (ret < 0)
>  		goto error;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> index dcde6288da6c..2b02eccbfb70 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> @@ -743,8 +743,8 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
>  
>  		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
>  					       &rcar_du_plane_funcs, formats,
> -					       ARRAY_SIZE(formats), type,
> -					       NULL);
> +					       ARRAY_SIZE(formats),
> +					       NULL, type, NULL);
>  		if (ret < 0)
>  			return ret;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> index b5bfbe50bd87..744be029436b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> @@ -364,8 +364,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
>  					       1 << vsp->index,
>  					       &rcar_du_vsp_plane_funcs,
>  					       formats_kms,
> -					       ARRAY_SIZE(formats_kms), type,
> -					       NULL);
> +					       ARRAY_SIZE(formats_kms),
> +					       NULL,
> +					       type, NULL);
>  		if (ret < 0)
>  			return ret;
>  
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index fb5f001f51c3..826b376114f6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -1221,7 +1221,7 @@ static int vop_create_crtc(struct vop *vop)
>  					       0, &vop_plane_funcs,
>  					       win_data->phy->data_formats,
>  					       win_data->phy->nformats,
> -					       win_data->type, NULL);
> +					       NULL, win_data->type, NULL);
>  		if (ret) {
>  			DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
>  				      ret);
> @@ -1260,7 +1260,7 @@ static int vop_create_crtc(struct vop *vop)
>  					       &vop_plane_funcs,
>  					       win_data->phy->data_formats,
>  					       win_data->phy->nformats,
> -					       win_data->type, NULL);
> +					       NULL, win_data->type, NULL);
>  		if (ret) {
>  			DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
>  				      ret);
> diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
> index cca75bddb9ad..f61808b419a5 100644
> --- a/drivers/gpu/drm/sti/sti_cursor.c
> +++ b/drivers/gpu/drm/sti/sti_cursor.c
> @@ -393,6 +393,7 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
>  				       &sti_cursor_plane_helpers_funcs,
>  				       cursor_supported_formats,
>  				       ARRAY_SIZE(cursor_supported_formats),
> +				       NULL,
>  				       DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (res) {
>  		DRM_ERROR("Failed to initialize universal plane\n");
> diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
> index 877d053d86f4..6bf1a592cee4 100644
> --- a/drivers/gpu/drm/sti/sti_gdp.c
> +++ b/drivers/gpu/drm/sti/sti_gdp.c
> @@ -921,7 +921,7 @@ struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
>  				       &sti_gdp_plane_helpers_funcs,
>  				       gdp_supported_formats,
>  				       ARRAY_SIZE(gdp_supported_formats),
> -				       type, NULL);
> +				       NULL, type, NULL);
>  	if (res) {
>  		DRM_ERROR("Failed to initialize universal plane\n");
>  		goto err;
> diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
> index becf10d255c4..911e8f0f69a6 100644
> --- a/drivers/gpu/drm/sti/sti_hqvdp.c
> +++ b/drivers/gpu/drm/sti/sti_hqvdp.c
> @@ -1277,7 +1277,7 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
>  				       &sti_hqvdp_plane_helpers_funcs,
>  				       hqvdp_supported_formats,
>  				       ARRAY_SIZE(hqvdp_supported_formats),
> -				       DRM_PLANE_TYPE_OVERLAY, NULL);
> +				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
>  	if (res) {
>  		DRM_ERROR("Failed to initialize universal plane\n");
>  		return NULL;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> index 5d53c977bca5..827f45364654 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -117,6 +117,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  	ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
>  				       &sun4i_backend_layer_funcs,
>  				       plane->formats, plane->nformats,
> +				       NULL,
>  				       plane->type, NULL);
>  	if (ret) {
>  		dev_err(drm->dev, "Couldn't initialize layer\n");
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index 7561a95a54e3..9ddea84208c4 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -655,8 +655,8 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
>  
>  	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
>  				       &tegra_primary_plane_funcs, formats,
> -				       num_formats, DRM_PLANE_TYPE_PRIMARY,
> -				       NULL);
> +				       num_formats, NULL,
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (err < 0) {
>  		kfree(plane);
>  		return ERR_PTR(err);
> @@ -821,8 +821,8 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
>  
>  	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
>  				       &tegra_cursor_plane_funcs, formats,
> -				       num_formats, DRM_PLANE_TYPE_CURSOR,
> -				       NULL);
> +				       num_formats, NULL,
> +				       DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (err < 0) {
>  		kfree(plane);
>  		return ERR_PTR(err);
> @@ -883,8 +883,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
>  
>  	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
>  				       &tegra_overlay_plane_funcs, formats,
> -				       num_formats, DRM_PLANE_TYPE_OVERLAY,
> -				       NULL);
> +				       num_formats, NULL,
> +				       DRM_PLANE_TYPE_OVERLAY, NULL);
>  	if (err < 0) {
>  		kfree(plane);
>  		return ERR_PTR(err);
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 110d1518f5d5..487bb40e0e4e 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -861,7 +861,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
>  	ret = drm_universal_plane_init(dev, plane, 0xff,
>  				       &vc4_plane_funcs,
>  				       formats, num_formats,
> -				       type, NULL);
> +				       NULL, type, NULL);
>  
>  	drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
>  
> diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
> index 11288ffa4af6..00f368cde0b8 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_plane.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
> @@ -225,7 +225,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
>  	ret = drm_universal_plane_init(dev, plane, 1 << index,
>  				       &virtio_gpu_plane_funcs,
>  				       formats, nformats,
> -				       type, NULL);
> +				       NULL, type, NULL);
>  	if (ret)
>  		goto err_plane_init;
>  
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index b634b090cdc1..c57d4fe5da18 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -287,7 +287,7 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
>  
>  	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
>  				       &zx_plane_funcs, formats, format_count,
> -				       type, NULL);
> +				       NULL, type, NULL);
>  	if (ret) {
>  		DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
>  		return ERR_PTR(ret);
> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index e049bc52fb07..108a955438e5 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -389,6 +389,20 @@ struct drm_plane_funcs {
>  	 */
>  	void (*atomic_print_state)(struct drm_printer *p,
>  				   const struct drm_plane_state *state);
> +
> +	/**
> +	 * @format_mod_supported:
> +	 *
> +	 * This optional hook is used for the DRM to determine if the given
> +	 * format/modifier combination is valid for the plane. This allows the
> +	 * DRM to generate the correct format bitmask (which formats apply to
> +	 * which modifier).
> +	 *
> +	 * True if the given modifier is valid for that format on the plane.
> +	 * False otherwise.
> +	 */
> +	bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,
> +				     uint64_t modifier);
>  };
>  
>  /**
> @@ -483,6 +497,10 @@ struct drm_plane {
>  	unsigned int format_count;
>  	bool format_default;
>  
> +	uint32_t *formats;
> +	uint64_t *modifiers;
> +	unsigned int modifier_count;
> +
>  	struct drm_crtc *crtc;
>  	struct drm_framebuffer *fb;
>  
> @@ -510,13 +528,14 @@ struct drm_plane {
>  
>  #define obj_to_plane(x) container_of(x, struct drm_plane, base)
>  
> -extern __printf(8, 9)
> +extern __printf(9, 10)
>  int drm_universal_plane_init(struct drm_device *dev,
>  			     struct drm_plane *plane,
>  			     uint32_t possible_crtcs,
>  			     const struct drm_plane_funcs *funcs,
>  			     const uint32_t *formats,
>  			     unsigned int format_count,
> +			     const uint64_t *format_modifiers,
>  			     enum drm_plane_type type,
>  			     const char *name, ...);
>  extern int drm_plane_init(struct drm_device *dev,
> diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
> index fe8c4ba905ac..059cd592a127 100644
> --- a/include/drm/drm_simple_kms_helper.h
> +++ b/include/drm/drm_simple_kms_helper.h
> @@ -118,6 +118,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
>  			struct drm_simple_display_pipe *pipe,
>  			const struct drm_simple_display_pipe_funcs *funcs,
>  			const uint32_t *formats, unsigned int format_count,
> +			const uint64_t *format_modifiers,
>  			struct drm_connector *connector);
>  
>  #endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index b2c52843bc70..487e0f17113f 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -805,6 +805,7 @@ extern "C" {
>  #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
>  #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
>  #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
> +#define DRM_IOCTL_MODE_GETPLANE2	DRM_IOWR(0xB6, struct drm_mode_get_plane2)
>  #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
>  #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
>  #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> index 4581e3d41e5c..5859014d93c7 100644
> --- a/include/uapi/drm/drm_fourcc.h
> +++ b/include/uapi/drm/drm_fourcc.h
> @@ -162,6 +162,8 @@ extern "C" {
>  #define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
>  /* add more to the end as needed */
>  
> +#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
> +
>  #define fourcc_mod_code(vendor, val) \
>  	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
>  
> @@ -174,6 +176,15 @@ extern "C" {
>   */
>  
>  /*
> + * Invalid Modifier
> + *
> + * This modifier can be used as a sentinel to terminate list, or to initialize a
> + * variable with an invalid modifier. It might also be used to report an error
> + * back to userspace for certain APIs.
> + */
> +#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
> +
> +/*
>   * Linear Layout
>   *
>   * Just plain linear layout. Note that this is different from no specifying any
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index ce7efe2e8a5e..63932b28ddd0 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -209,6 +209,42 @@ struct drm_mode_get_plane {
>  	__u64 format_type_ptr;
>  };
>  
> +struct drm_format_modifier {
> +	/* Bitmask of formats in get_plane format list this info applies to. The
> +	 * offset allows a sliding window of which 32 formats (bits).
> +	 *
> +	 * For example, if the formats grew to 128, and the last formats were
> +	 * supported with the modifier:
> +	 *
> +	 * 0xFFFFFFFF 00000000 00000000 00000000
> +	 *          ^
> +	 *          |__offset = 96, formats = 0xffffffff
> +	 */

I don't quite understand what this is trying to say.

Hmm. Is that 0xFFFF... thing the full 128 bit mask of formats? The all
1s and all 0s patterns are maybe a bit too magic looking. Might be better
to have some more randomish looking bit patterns in the example so that
the reders doesn't make the assumption that the values are somehow
special. And actually showing the offset+formats pair for each dword
in the example bitmask might make it even more clear.

> +	uint32_t formats;
> +	uint32_t offset;
> +
> +	/* This modifier can be used with the format for this plane. */
> +	uint64_t modifier;
> +};
> +
> +struct drm_mode_get_plane2 {
> +	__u32 plane_id;
> +
> +	__u32 crtc_id;
> +	__u32 fb_id;
> +
> +	__u32 possible_crtcs;
> +	__u32 gamma_size;
> +
> +	__u32 count_format_types;
> +	__u64 format_type_ptr;
> +
> +	/* New in v2 */
> +	__u32 flags;
> +	__u32 count_format_modifiers;
> +	__u64 format_modifier_ptr;
> +};
> +
>  struct drm_mode_get_plane_res {
>  	__u64 plane_id_ptr;
>  	__u32 count_planes;
> -- 
> 2.11.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/3] [v3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-25  5:20   ` [PATCH 1/3] [v2] " Ben Widawsky
  2017-01-25 15:28     ` Ville Syrjälä
@ 2017-01-26 23:34     ` Ben Widawsky
  1 sibling, 0 replies; 28+ messages in thread
From: Ben Widawsky @ 2017-01-26 23:34 UTC (permalink / raw)
  To: DRI Development, Intel GFX; +Cc: Ben Widawsky, Kristian H. Kristensen

Originally based off of a patch by Kristian.

This new ioctl extends DRM_IOCTL_MODE_GETPLANE, by returning information
about the modifiers that will work with each format.

It's modified from Kristian's patch in that the modifiers and formats
are setup by the driver, and then a callback is used to create the
format list. The LOC was enough difference that I don't think it made
sense to leave his authorship, but the new UABI was primarily his idea.

Additionally, I hit a couple of drivers which Kristian missed updating.

It also contains a change requested by Daniel to make the modifiers
array a sentinel based structure instead of a sized one. Upon discussion
on IRC, it was determined that having an invalid modifier might make
sense in general as well.

v2:
  - Make formats uint32_t, and use an offset, see the comment in the
  patch. Add a WARN_ON and early bail for when there are more than 32
  formats. (Rob)
  - Remove DRM_DEBUG_KMS (Ville)
  - make flags come before count in struct (Ville)

v3:
  - Make formats 64b again to defer the pain, and add a pad
  - Make init fail if > 64 instead of at get_plane. This could be made
  more optimal by doing it in get_plane because 0 masked modifiers don't
  need to be reported back to userspace. As a result, the first driver
  to go back 64 formats has to deal with this.
  - Fix the comment to be more clear.

Cc: Rob Clark <robdclark@gmail.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Stone <daniel@fooishbar.org>
Cc: "Kristian H. Kristensen" <hoegsberg@gmail.com>
References: https://patchwork.kernel.org/patch/9482393/
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/arc/arcpgu_crtc.c               |  1 +
 drivers/gpu/drm/arm/hdlcd_crtc.c                |  1 +
 drivers/gpu/drm/arm/malidp_planes.c             |  2 +-
 drivers/gpu/drm/armada/armada_crtc.c            |  1 +
 drivers/gpu/drm/armada/armada_overlay.c         |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |  4 +-
 drivers/gpu/drm/drm_ioctl.c                     |  2 +-
 drivers/gpu/drm/drm_modeset_helper.c            |  1 +
 drivers/gpu/drm/drm_plane.c                     | 67 ++++++++++++++++++++++++-
 drivers/gpu/drm/drm_simple_kms_helper.c         |  3 ++
 drivers/gpu/drm/exynos/exynos_drm_plane.c       |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |  1 +
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c            |  7 ++-
 drivers/gpu/drm/i915/intel_sprite.c             |  4 +-
 drivers/gpu/drm/imx/ipuv3-plane.c               |  4 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c        |  2 +-
 drivers/gpu/drm/meson/meson_plane.c             |  1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |  2 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.c               |  2 +-
 drivers/gpu/drm/nouveau/nv50_display.c          |  5 +-
 drivers/gpu/drm/omapdrm/omap_plane.c            |  3 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +-
 drivers/gpu/drm/sti/sti_cursor.c                |  1 +
 drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c             |  1 +
 drivers/gpu/drm/tegra/dc.c                      | 12 ++---
 drivers/gpu/drm/vc4/vc4_plane.c                 |  2 +-
 drivers/gpu/drm/virtio/virtgpu_plane.c          |  2 +-
 drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
 include/drm/drm_plane.h                         | 21 +++++++-
 include/drm/drm_simple_kms_helper.h             |  1 +
 include/uapi/drm/drm.h                          |  1 +
 include/uapi/drm/drm_fourcc.h                   | 11 ++++
 include/uapi/drm/drm_mode.h                     | 44 ++++++++++++++++
 40 files changed, 199 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
index ad9a95916f1f..cd8a24c7c67d 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -218,6 +218,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 20ebfb4fbdfa..89fded880807 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -283,6 +283,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
 
 	ret = drm_universal_plane_init(drm, plane, 0xff, &hdlcd_plane_funcs,
 				       formats, ARRAY_SIZE(formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		devm_kfree(drm->dev, plane);
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index eff2fe47e26a..94dbcbc9ad8f 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -283,7 +283,7 @@ int malidp_de_planes_init(struct drm_device *drm)
 					DRM_PLANE_TYPE_OVERLAY;
 		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
 					       &malidp_de_plane_funcs, formats,
-					       n, plane_type, NULL);
+					       n, NULL, plane_type, NULL);
 		if (ret < 0)
 			goto cleanup;
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e62ee4498ce4..39330145ba2a 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1250,6 +1250,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 				       &armada_primary_plane_funcs,
 				       armada_primary_formats,
 				       ARRAY_SIZE(armada_primary_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 34cb73d0db77..6a1ca8aa8e16 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -458,6 +458,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 				       &armada_ovl_plane_funcs,
 				       armada_ovl_formats,
 				       ARRAY_SIZE(armada_ovl_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (ret) {
 		kfree(dplane);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index bd2791c4b002..f12cec0bc58c 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -1038,7 +1038,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, &plane->base, 0,
 				       &layer_plane_funcs,
 				       desc->formats->formats,
-				       desc->formats->nformats, type, NULL);
+				       desc->formats->nformats,
+				       NULL,
+				       type, NULL);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a7c61c23685a..c820d99d9231 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -614,7 +614,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE2, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index 2b33825f2f93..9cb1eede0b4d 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
 				       &drm_primary_helper_funcs,
 				       safe_modeset_formats,
 				       ARRAY_SIZE(safe_modeset_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 7b7275f0c2df..706c2b7479cb 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
  * @funcs: callbacks for the new plane
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of struct drm_format modifiers terminated by INVALID
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default name
  *
@@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats, unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...)
 {
 	struct drm_mode_config *config = &dev->mode_config;
+	unsigned int format_modifier_count = 0;
 	int ret;
 
 	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +108,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		return -ENOMEM;
 	}
 
+	/* First driver to need more than 64 formats needs to fix this */
+	if (WARN_ON(format_count > 64))
+		return -EINVAL;
+
+	if (format_modifiers) {
+		const uint64_t *temp_modifiers = format_modifiers;
+		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
+			format_modifier_count++;
+	}
+
+	plane->modifier_count = format_modifier_count;
+	plane->modifiers = kmalloc_array(format_modifier_count,
+					 sizeof(format_modifiers[0]),
+					 GFP_KERNEL);
+
+	if (format_modifier_count && !plane->modifiers) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		kfree(plane->format_types);
+		drm_mode_object_unregister(dev, &plane->base);
+		return -ENOMEM;
+	}
+
 	if (name) {
 		va_list ap;
 
@@ -117,12 +142,15 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 	}
 	if (!plane->name) {
 		kfree(plane->format_types);
+		kfree(plane->modifiers);
 		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
 	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 	plane->format_count = format_count;
+	memcpy(plane->modifiers, format_modifiers,
+	       format_modifier_count * sizeof(format_modifiers[0]));
 	plane->possible_crtcs = possible_crtcs;
 	plane->type = type;
 
@@ -205,7 +233,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-					formats, format_count, type, NULL);
+					formats, format_count,
+					NULL, type, NULL);
 }
 EXPORT_SYMBOL(drm_plane_init);
 
@@ -224,6 +253,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
 	drm_modeset_lock_fini(&plane->mutex);
 
 	kfree(plane->format_types);
+	kfree(plane->modifiers);
 	drm_mode_object_unregister(dev, &plane->base);
 
 	BUG_ON(list_empty(&plane->head));
@@ -380,12 +410,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
 int drm_mode_getplane(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv)
 {
-	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_get_plane2 *plane_resp = data;
 	struct drm_plane *plane;
 	uint32_t __user *format_ptr;
+	struct drm_format_modifier __user *modifier_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
+	if (plane_resp->flags)
+		return -EINVAL;
 
 	plane = drm_plane_find(dev, plane_resp->plane_id);
 	if (!plane)
@@ -426,6 +459,36 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 	}
 	plane_resp->count_format_types = plane->format_count;
 
+	if (plane->modifier_count &&
+	    plane_resp->count_format_modifiers >= plane->modifier_count) {
+		struct drm_format_modifier mod = {0};
+		int i;
+
+		modifier_ptr = (struct drm_format_modifier __user *)
+			(unsigned long)plane_resp->format_modifier_ptr;
+
+		/* Build the mask for each modifier */
+		for (i = 0; i < plane->modifier_count; i++) {
+			int j;
+			mod.modifier = plane->modifiers[i];
+			for (j = 0; j < plane->format_count; j++) {
+				if (plane->funcs->format_mod_supported &&
+				    plane->funcs->format_mod_supported(plane,
+								       plane->format_types[j],
+								       plane->modifiers[i])) {
+					mod.formats |= 1 << j;
+				}
+			}
+
+			if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
+				return -EFAULT;
+
+			modifier_ptr++;
+		}
+	}
+
+	plane_resp->count_format_modifiers = plane->modifier_count;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 35c5d99296b9..6c099694fccb 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -193,6 +193,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
  * @funcs: callbacks for the display pipe (optional)
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of formats modifiers
  * @connector: connector to attach and register (optional)
  *
  * Sets up a display pipeline which consist of a really simple
@@ -213,6 +214,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &pipe->encoder;
@@ -227,6 +229,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0,
 				       &drm_simple_kms_plane_funcs,
 				       formats, format_count,
+				       format_modifiers,
 				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c2f17f30afab..75d4928dd196 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -284,7 +284,7 @@ int exynos_plane_init(struct drm_device *dev,
 				       &exynos_plane_funcs,
 				       config->pixel_formats,
 				       config->num_pixel_formats,
-				       config->type, NULL);
+				       NULL, config->type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index 0a20723aa6e1..9554b245746e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -224,7 +224,7 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 				       &fsl_dcu_drm_plane_funcs,
 				       fsl_dcu_drm_plane_formats,
 				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		kfree(primary);
 		primary = NULL;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index c655883d3613..919cc807809f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -181,6 +181,7 @@ static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
 	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
 				       channel_formats1,
 				       ARRAY_SIZE(channel_formats1),
+				       NULL,
 				       DRM_PLANE_TYPE_PRIMARY,
 				       NULL);
 	if (ret) {
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index 307d460ab684..b433b8e7c9cd 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -911,7 +911,7 @@ static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane,
 		return ret;
 
 	ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs,
-				       fmts, fmts_cnt, type, NULL);
+				       fmts, fmts_cnt, NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
 		return ret;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b547332eeda1..8715b1083d1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15303,6 +15303,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 					      src_x, src_y, src_w, src_h);
 }
 
+
+
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
 	.update_plane = intel_legacy_cursor_update,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -15387,18 +15389,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
 	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
+					       NULL,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
@@ -15563,7 +15568,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 				       0, &intel_cursor_plane_funcs,
 				       intel_cursor_formats,
 				       ARRAY_SIZE(intel_cursor_formats),
-				       DRM_PLANE_TYPE_CURSOR,
+				       NULL, DRM_PLANE_TYPE_CURSOR,
 				       "cursor %c", pipe_name(pipe));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 063a994815d0..1c2f26d86f76 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1127,13 +1127,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       DRM_PLANE_TYPE_OVERLAY,
+					       NULL, DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 8b5294d47cee..ef9e11b98b3c 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -496,8 +496,8 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
 
 	ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
 				       &ipu_plane_funcs, ipu_plane_formats,
-				       ARRAY_SIZE(ipu_plane_formats), type,
-				       NULL);
+				       ARRAY_SIZE(ipu_plane_formats),
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_ERROR("failed to initialize plane\n");
 		kfree(ipu_plane);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index e405e89ed5e5..bec6d14dd070 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -173,7 +173,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	err = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &mtk_plane_funcs, formats,
-				       ARRAY_SIZE(formats), type, NULL);
+				       ARRAY_SIZE(formats), NULL, type, NULL);
 	if (err) {
 		DRM_ERROR("failed to initialize plane\n");
 		return err;
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 642b2fab42ff..13c7c2c1d4cc 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -220,6 +220,7 @@ int meson_plane_create(struct meson_drm *priv)
 				 &meson_plane_funcs,
 				 supported_drm_formats,
 				 ARRAY_SIZE(supported_drm_formats),
+				 NULL,
 				 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
 
 	drm_plane_helper_add(plane, &meson_plane_helper_funcs);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 53619d07677e..8f3417e45d4e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -398,7 +398,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
 				 mdp4_plane->formats, mdp4_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 75247ea4335b..c2068c30ca73 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -882,7 +882,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
-				 type, NULL);
+				 NULL, type, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 955441f71500..f29d463e03a4 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -186,7 +186,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 	}
 
 	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
-			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+			mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL, 0,
 			&mxsfb->connector);
 	if (ret < 0) {
 		dev_err(drm->dev, "Cannot setup simple display pipe\n");
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index cb85cb72dc1c..cf5ed98caed4 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1079,8 +1079,9 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
 	wndw->func = func;
 	wndw->dmac = dmac;
 
-	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
-				       nformat, type, "%s-%d", name, index);
+	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw,
+				       format, nformat, NULL,
+				       type, "%s-%d", name, index);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 82b2c23d6769..b4a575cf7e71 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -383,7 +383,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &omap_plane_funcs, omap_plane->formats,
-				       omap_plane->nformats, type, NULL);
+				       omap_plane->nformats,
+				       NULL, type, NULL);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index dcde6288da6c..2b02eccbfb70 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -743,8 +743,8 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
 
 		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
 					       &rcar_du_plane_funcs, formats,
-					       ARRAY_SIZE(formats), type,
-					       NULL);
+					       ARRAY_SIZE(formats),
+					       NULL, type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index b5bfbe50bd87..744be029436b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -364,8 +364,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 					       1 << vsp->index,
 					       &rcar_du_vsp_plane_funcs,
 					       formats_kms,
-					       ARRAY_SIZE(formats_kms), type,
-					       NULL);
+					       ARRAY_SIZE(formats_kms),
+					       NULL,
+					       type, NULL);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fb5f001f51c3..826b376114f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1221,7 +1221,7 @@ static int vop_create_crtc(struct vop *vop)
 					       0, &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
 				      ret);
@@ -1260,7 +1260,7 @@ static int vop_create_crtc(struct vop *vop)
 					       &vop_plane_funcs,
 					       win_data->phy->data_formats,
 					       win_data->phy->nformats,
-					       win_data->type, NULL);
+					       NULL, win_data->type, NULL);
 		if (ret) {
 			DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
 				      ret);
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index cca75bddb9ad..f61808b419a5 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -393,6 +393,7 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
 				       &sti_cursor_plane_helpers_funcs,
 				       cursor_supported_formats,
 				       ARRAY_SIZE(cursor_supported_formats),
+				       NULL,
 				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 877d053d86f4..6bf1a592cee4 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -921,7 +921,7 @@ struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
 				       &sti_gdp_plane_helpers_funcs,
 				       gdp_supported_formats,
 				       ARRAY_SIZE(gdp_supported_formats),
-				       type, NULL);
+				       NULL, type, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		goto err;
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index becf10d255c4..911e8f0f69a6 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1277,7 +1277,7 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
 				       &sti_hqvdp_plane_helpers_funcs,
 				       hqvdp_supported_formats,
 				       ARRAY_SIZE(hqvdp_supported_formats),
-				       DRM_PLANE_TYPE_OVERLAY, NULL);
+				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 5d53c977bca5..827f45364654 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -117,6 +117,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
 				       &sun4i_backend_layer_funcs,
 				       plane->formats, plane->nformats,
+				       NULL,
 				       plane->type, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 7561a95a54e3..9ddea84208c4 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -655,8 +655,8 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
 				       &tegra_primary_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_PRIMARY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -821,8 +821,8 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_cursor_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_CURSOR,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -883,8 +883,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
 
 	err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
 				       &tegra_overlay_plane_funcs, formats,
-				       num_formats, DRM_PLANE_TYPE_OVERLAY,
-				       NULL);
+				       num_formats, NULL,
+				       DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 110d1518f5d5..487bb40e0e4e 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -861,7 +861,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
 	ret = drm_universal_plane_init(dev, plane, 0xff,
 				       &vc4_plane_funcs,
 				       formats, num_formats,
-				       type, NULL);
+				       NULL, type, NULL);
 
 	drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 11288ffa4af6..00f368cde0b8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -225,7 +225,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
 	ret = drm_universal_plane_init(dev, plane, 1 << index,
 				       &virtio_gpu_plane_funcs,
 				       formats, nformats,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret)
 		goto err_plane_init;
 
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index b634b090cdc1..c57d4fe5da18 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -287,7 +287,7 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
 
 	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
 				       &zx_plane_funcs, formats, format_count,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
 		return ERR_PTR(ret);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index e049bc52fb07..108a955438e5 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -389,6 +389,20 @@ struct drm_plane_funcs {
 	 */
 	void (*atomic_print_state)(struct drm_printer *p,
 				   const struct drm_plane_state *state);
+
+	/**
+	 * @format_mod_supported:
+	 *
+	 * This optional hook is used for the DRM to determine if the given
+	 * format/modifier combination is valid for the plane. This allows the
+	 * DRM to generate the correct format bitmask (which formats apply to
+	 * which modifier).
+	 *
+	 * True if the given modifier is valid for that format on the plane.
+	 * False otherwise.
+	 */
+	bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,
+				     uint64_t modifier);
 };
 
 /**
@@ -483,6 +497,10 @@ struct drm_plane {
 	unsigned int format_count;
 	bool format_default;
 
+	uint32_t *formats;
+	uint64_t *modifiers;
+	unsigned int modifier_count;
+
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 
@@ -510,13 +528,14 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-extern __printf(8, 9)
+extern __printf(9, 10)
 int drm_universal_plane_init(struct drm_device *dev,
 			     struct drm_plane *plane,
 			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats,
 			     unsigned int format_count,
+			     const uint64_t *format_modifiers,
 			     enum drm_plane_type type,
 			     const char *name, ...);
 extern int drm_plane_init(struct drm_device *dev,
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index fe8c4ba905ac..059cd592a127 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -118,6 +118,7 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
 			struct drm_simple_display_pipe *pipe,
 			const struct drm_simple_display_pipe_funcs *funcs,
 			const uint32_t *formats, unsigned int format_count,
+			const uint64_t *format_modifiers,
 			struct drm_connector *connector);
 
 #endif /* __LINUX_DRM_SIMPLE_KMS_HELPER_H */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b2c52843bc70..487e0f17113f 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -805,6 +805,7 @@ extern "C" {
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_GETPLANE2	DRM_IOWR(0xB6, struct drm_mode_get_plane2)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 4581e3d41e5c..5859014d93c7 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -162,6 +162,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
 /* add more to the end as needed */
 
+#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
+
 #define fourcc_mod_code(vendor, val) \
 	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
 
@@ -174,6 +176,15 @@ extern "C" {
  */
 
 /*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate list, or to initialize a
+ * variable with an invalid modifier. It might also be used to report an error
+ * back to userspace for certain APIs.
+ */
+#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
+/*
  * Linear Layout
  *
  * Just plain linear layout. Note that this is different from no specifying any
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ce7efe2e8a5e..f09eada74ec1 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -209,6 +209,50 @@ struct drm_mode_get_plane {
 	__u64 format_type_ptr;
 };
 
+struct drm_format_modifier {
+	/* Bitmask of formats in get_plane format list this info applies to. The
+	 * offset allows a sliding window of which 64 formats (bits).
+	 *
+	 * Some examples:
+	 * In today's world with < 65 formats, and formats 0, and 2 are
+	 * supported
+	 * 0x0000000000000005
+	 *                  ^-offset = 0, formats = 5
+	 *
+	 * If the number formats grew to 128, and formats 98-102 are
+	 * supported with the modifier:
+	 *
+	 * 0x0000003c00000000 0000000000000000
+	 *                  ^
+	 *                  |__offset = 64, formats = 0x3c00000000
+	 *
+	 */
+	uint64_t formats;
+	uint32_t offset;
+	uint32_t pad;
+
+	/* This modifier can be used with the format for this plane. */
+	uint64_t modifier;
+};
+
+struct drm_mode_get_plane2 {
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+	__u64 format_type_ptr;
+
+	/* New in v2 */
+	__u32 flags;
+	__u32 count_format_modifiers;
+	__u64 format_modifier_ptr;
+};
+
 struct drm_mode_get_plane_res {
 	__u64 plane_id_ptr;
 	__u32 count_planes;
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev3)
  2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
                   ` (4 preceding siblings ...)
  2017-01-25  6:32 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev2) Patchwork
@ 2017-01-27  1:02 ` Patchwork
  5 siblings, 0 replies; 28+ messages in thread
From: Patchwork @ 2017-01-27  1:02 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx

== Series Details ==

Series: GET_PLANE2 w/ i915 implementation (rev3)
URL   : https://patchwork.freedesktop.org/series/17873/
State : failure

== Summary ==

  CC [M]  drivers/gpu/drm/i915/gvt/cmd_parser.o
  CC [M]  drivers/gpu/drm/i915/gvt/sched_policy.o
  CC [M]  drivers/gpu/drm/i915/intel_lpe_audio.o
  CC [M]  drivers/gpu/drm/i915/gvt/render.o
  LD      drivers/iommu/built-in.o
  LD      drivers/tty/serial/8250/8250.o
  LD      lib/raid6/raid6_pq.o
  LD      lib/raid6/built-in.o
  LD      drivers/usb/storage/usb-storage.o
  LD      drivers/pci/pcie/aer/aerdriver.o
  LD      drivers/pci/pcie/aer/built-in.o
  LD      drivers/usb/storage/built-in.o
  LD      drivers/pci/pcie/built-in.o
  LD [M]  drivers/gpu/drm/vgem/vgem.o
  LD      drivers/spi/built-in.o
  LD      drivers/scsi/scsi_mod.o
  LD      drivers/video/fbdev/core/fb.o
  LD [M]  drivers/usb/serial/usbserial.o
  LD      drivers/video/fbdev/core/built-in.o
  LD      drivers/video/fbdev/built-in.o
  LD      drivers/pci/built-in.o
  LD      drivers/video/console/built-in.o
drivers/gpu/drm/i915/intel_display.c:100:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_display.c:101:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
  LD      drivers/video/built-in.o
drivers/gpu/drm/i915/intel_sprite.c:1043:2: error: ‘I915_FORMAT_MOD_Yf_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Yf_TILED_CCS,
  ^
drivers/gpu/drm/i915/intel_sprite.c:1044:2: error: ‘I915_FORMAT_MOD_Y_TILED_CCS’ undeclared here (not in a function)
  I915_FORMAT_MOD_Y_TILED_CCS,
  ^
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_sprite.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_sprite.o] Error 1
make[4]: *** Waiting for unfinished jobs....
  LD      drivers/usb/gadget/udc/udc-core.o
  LD      drivers/usb/gadget/udc/built-in.o
  LD      drivers/usb/gadget/libcomposite.o
  LD      net/ipv6/ipv6.o
  LD [M]  drivers/net/ethernet/broadcom/genet/genet.o
  LD      drivers/usb/gadget/built-in.o
drivers/gpu/drm/i915/intel_display.c: In function ‘skl_mod_supported’:
drivers/gpu/drm/i915/intel_display.c:15056:20: error: comparison between pointer and integer [-Werror]
   return  modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
                    ^
drivers/gpu/drm/i915/intel_display.c:15057:13: error: comparison between pointer and integer [-Werror]
    modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
             ^
  LD      net/ipv6/built-in.o
  AR      lib/lib.a
  LD      drivers/tty/serial/8250/8250_base.o
  LD      drivers/tty/serial/8250/built-in.o
  EXPORTS lib/lib-ksyms.o
  LD      drivers/tty/serial/built-in.o
  LD      lib/built-in.o
cc1: all warnings being treated as errors
  LD      drivers/scsi/sd_mod.o
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_display.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_display.o] Error 1
  LD      drivers/scsi/built-in.o
  LD      net/ipv4/built-in.o
  LD      fs/btrfs/btrfs.o
  LD [M]  drivers/net/ethernet/intel/igbvf/igbvf.o
  LD      drivers/tty/vt/built-in.o
  LD      drivers/tty/built-in.o
  LD      drivers/gpu/drm/drm.o
  LD      drivers/usb/core/usbcore.o
  LD      fs/btrfs/built-in.o
  LD      drivers/usb/core/built-in.o
  CC      arch/x86/kernel/cpu/capflags.o
  LD      arch/x86/kernel/cpu/built-in.o
  LD      arch/x86/kernel/built-in.o
  LD      drivers/usb/host/xhci-hcd.o
  LD      drivers/md/md-mod.o
  LD      drivers/md/built-in.o
  LD      arch/x86/built-in.o
  LD [M]  drivers/net/ethernet/intel/e1000/e1000.o
  LD      fs/ext4/ext4.o
  LD      net/core/built-in.o
  LD      fs/ext4/built-in.o
  LD      net/built-in.o
  LD      fs/built-in.o
  LD      drivers/usb/host/built-in.o
  LD      drivers/usb/built-in.o
  LD [M]  drivers/net/ethernet/intel/e1000e/e1000e.o
  LD [M]  drivers/net/ethernet/intel/igb/igb.o
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:551: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
make[1]: *** Waiting for unfinished jobs....
  LD      drivers/net/ethernet/built-in.o
  LD      drivers/net/built-in.o
Makefile:988: recipe for target 'drivers' failed
make: *** [drivers] Error 2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2
  2017-01-12 10:23   ` [Intel-gfx] " Ville Syrjälä
@ 2023-11-24 15:08     ` Andy Shevchenko
  0 siblings, 0 replies; 28+ messages in thread
From: Andy Shevchenko @ 2023-11-24 15:08 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ben Widawsky, Intel GFX, DRI Development

On Thu, Jan 12, 2017 at 12:23:16PM +0200, Ville Syrjälä wrote:
> On Wed, Jan 11, 2017 at 04:51:16PM -0800, Ben Widawsky wrote:

...

> > +	memcpy(plane->modifiers, format_modifiers,
> > +	       format_modifier_count * sizeof(format_modifiers[0]));
> 
> Looks all right since we do the same for formats anyway. But it did
> occur to me (twice at least) that a kmemdup_array() might a nice thing
> to have for things like this. But that's a separate topic.

JFYI:
https://lore.kernel.org/all/20231017052322.2636-2-kkartik@nvidia.com/

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2023-11-24 15:23 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-12  0:51 [PATCH 0/3] GET_PLANE2 w/ i915 implementation Ben Widawsky
2017-01-12  0:51 ` [PATCH 1/3] drm: Add new DRM_IOCTL_MODE_GETPLANE2 Ben Widawsky
2017-01-12  1:43   ` [Intel-gfx] " Rob Clark
2017-01-12  9:38     ` Ville Syrjälä
2017-01-12 14:56       ` Rob Clark
2017-01-12 17:04         ` Daniel Stone
2017-01-12 17:45           ` Ville Syrjälä
2017-01-12 17:50             ` Daniel Stone
2017-01-12 18:11               ` Ville Syrjälä
2017-01-12 19:27                 ` Daniel Stone
2017-01-13  9:37                   ` [Intel-gfx] " Ville Syrjälä
2017-01-13  9:45                     ` Daniel Stone
2017-01-12 10:23   ` [Intel-gfx] " Ville Syrjälä
2023-11-24 15:08     ` Andy Shevchenko
2017-01-25  5:20   ` [PATCH 1/3] [v2] " Ben Widawsky
2017-01-25 15:28     ` Ville Syrjälä
2017-01-26 23:34     ` [PATCH 1/3] [v3] " Ben Widawsky
2017-01-12  0:51 ` [PATCH 2/3] drm/i915: Add format modifiers for Intel Ben Widawsky
2017-01-12 10:51   ` Ville Syrjälä
2017-01-12 18:00     ` Ben Widawsky
2017-01-12 18:32       ` Ville Syrjälä
2017-01-12 18:56         ` Ben Widawsky
2017-01-13  9:35           ` Ville Syrjälä
2017-01-12  0:51 ` [PATCH 3/3] drm/i915: Add support for GET_PLANE2 CCS modifiers Ben Widawsky
2017-01-12  1:01 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation Patchwork
2017-01-12  1:23   ` Ben Widawsky
2017-01-25  6:32 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev2) Patchwork
2017-01-27  1:02 ` ✗ Fi.CI.BAT: failure for GET_PLANE2 w/ i915 implementation (rev3) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.