[v3,1/3] drm: Plumb modifiers through plane init

Submitted by Ben Widawsky on May 16, 2017, 9:31 p.m.

Details

Message ID 20170516213126.8269-1-ben@bwidawsk.net
State New
Headers show
Series "Series without cover letter" ( rev: 3 2 1 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Ben Widawsky May 16, 2017, 9:31 p.m.
This is the plumbing for supporting fb modifiers on planes. Modifiers
have already been introduced to some extent, but this series will extend
this to allow querying modifiers per plane. Based on this, the client to
enable optimal modifications for framebuffers.

This patch simply allows the DRM drivers to initialize their list of
supported modifiers upon initializing the plane.

v2: A minor addition from Daniel

v3: Updated commit message
s/INVALID/DRM_FORMAT_MOD_INVALID (Liviu)
Remove some excess newlines (Liviu)
Update comment for > 64 modifiers (Liviu)

Cc: Liviu Dudau <Liviu.Dudau@arm.com>
Reviewed-by: Daniel Stone <daniels@collabora.com> (v2)
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_modeset_helper.c            |  1 +
 drivers/gpu/drm/drm_plane.c                     | 35 ++++++++++++++++++++++++-
 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            |  5 +++-
 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       |  4 +--
 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/qxl/qxl_display.c               |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +--
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  4 +--
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +--
 drivers/gpu/drm/sti/sti_cursor.c                |  2 +-
 drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
 drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c             |  2 +-
 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/vmwgfx/vmwgfx_ldu.c             |  4 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c            |  4 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c            |  4 +--
 drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
 include/drm/drm_plane.h                         | 20 +++++++++++++-
 include/drm/drm_simple_kms_helper.h             |  1 +
 include/uapi/drm/drm_fourcc.h                   | 11 ++++++++
 41 files changed, 126 insertions(+), 46 deletions(-)

Patch hide | download patch | download mbox

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 798a3cc480a2..0caa03ae8708 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -303,6 +303,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 814fda23cead..b156610c68a5 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -400,7 +400,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 4fe19fde84f9..ea48ef88f0e4 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1269,6 +1269,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 424e465ff407..0054144287ae 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -460,6 +460,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 29cc10d053eb..b5c6cf2d8c36 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -1058,7 +1058,9 @@  static int 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 ret;
 
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 fedd4d60d9cd..20203871e06d 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -70,6 +70,8 @@  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
+ *                    DRM_FORMAT_MOD_INVALID
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default name
  *
@@ -82,10 +84,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_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +109,30 @@  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. Each
+	 * format is encoded as a bit and the current code only supports a u64.
+	 */
+	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 +145,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 +236,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 +256,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));
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index e084f9f8ca66..949f0ab0e267 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 59542bddc980..339e914cbaa3 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 c96c228a9898..1acb8af12246 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -909,7 +909,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 3617927af269..9dd67d51e7c9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13594,18 +13594,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)
@@ -13776,7 +13779,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 f7d431427115..053802dd08c1 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1165,13 +1165,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 d63e853a0300..6c708c3b1cdc 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -718,8 +718,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 a32d3b6e2e12..17e96fa47868 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -223,6 +223,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 a38c5fe6cc19..a815bc0e78d1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -1140,12 +1140,12 @@  struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 		ret = drm_universal_plane_init(dev, plane, 0xff,
 				&mdp5_cursor_plane_funcs,
 				mdp5_plane->formats, mdp5_plane->nformats,
-				type, NULL);
+				NULL, type, NULL);
 	else
 		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 d1b9c34c7c00..3ee3784a54f4 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -190,7 +190,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 0e58537352fe..dde71be463f8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1084,8 +1084,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 9168154d749e..9b8341d77468 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -370,7 +370,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/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 058340a002c2..fcf1d2034449 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -788,7 +788,7 @@  static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
 
 	err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs,
 				       funcs, formats, num_formats,
-				       type, NULL);
+				       NULL, type, NULL);
 	if (err)
 		goto free_plane;
 
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 b0ff304ce3dc..e0c054f9b57a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -368,8 +368,8 @@  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 3f7a82d1e095..d0cf57de9afc 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1280,7 +1280,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);
@@ -1319,7 +1319,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..97c25e204bf4 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -393,7 +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),
-				       DRM_PLANE_TYPE_CURSOR, NULL);
+				       NULL, DRM_PLANE_TYPE_CURSOR, NULL);
 	if (res) {
 		DRM_ERROR("Failed to initialize universal plane\n");
 		goto err_plane;
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 88f16cdf6a4b..70391603c12d 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -932,7 +932,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 66f843148ef7..9a1ff352820d 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1296,7 +1296,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 f26bde5b9117..2d9f8d01ac2e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -115,7 +115,7 @@  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	ret = drm_universal_plane_init(drm, &layer->plane, 0,
 				       &sun4i_backend_layer_funcs,
 				       plane->formats, plane->nformats,
-				       plane->type, NULL);
+				       NULL, plane->type, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 95b373f739f2..0380edd054ac 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 d34cd5393a9b..74b5e7afd6e9 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, 0,
 				       &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 adcdbd0abef6..71ba455af915 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -298,7 +298,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/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index d3987bcf53f8..6f0bf6f9c6f8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -439,7 +439,7 @@  static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 				       0, &vmw_ldu_plane_funcs,
 				       vmw_primary_plane_formats,
 				       ARRAY_SIZE(vmw_primary_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize primary plane");
 		goto err_free;
@@ -454,7 +454,7 @@  static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 			0, &vmw_ldu_cursor_funcs,
 			vmw_cursor_plane_formats,
 			ARRAY_SIZE(vmw_cursor_plane_formats),
-			DRM_PLANE_TYPE_CURSOR, NULL);
+			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize cursor plane");
 		drm_plane_cleanup(&ldu->base.primary);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 8d7dc9def7c2..42780c9cb90f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -622,7 +622,7 @@  static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 				       0, &vmw_sou_plane_funcs,
 				       vmw_primary_plane_formats,
 				       ARRAY_SIZE(vmw_primary_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize primary plane");
 		goto err_free;
@@ -637,7 +637,7 @@  static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 			0, &vmw_sou_cursor_funcs,
 			vmw_cursor_plane_formats,
 			ARRAY_SIZE(vmw_cursor_plane_formats),
-			DRM_PLANE_TYPE_CURSOR, NULL);
+			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize cursor plane");
 		drm_plane_cleanup(&sou->base.primary);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index bad31bdf09b6..f18fb966ce9c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1456,7 +1456,7 @@  static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 				       0, &vmw_stdu_plane_funcs,
 				       vmw_primary_plane_formats,
 				       ARRAY_SIZE(vmw_primary_plane_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize primary plane");
 		goto err_free;
@@ -1471,7 +1471,7 @@  static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 			0, &vmw_stdu_cursor_funcs,
 			vmw_cursor_plane_formats,
 			ARRAY_SIZE(vmw_cursor_plane_formats),
-			DRM_PLANE_TYPE_CURSOR, NULL);
+			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize cursor plane");
 		drm_plane_cleanup(&stdu->base.primary);
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index d646ac931663..ea29fee01f7d 100644
--- a/drivers/gpu/drm/zte/zx_plane.c
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -539,7 +539,7 @@  int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
 
 	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 ret;
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 9ab3e7044812..2db5eed53d7b 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -392,6 +392,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);
 };
 
 /**
@@ -487,6 +501,9 @@  struct drm_plane {
 	unsigned int format_count;
 	bool format_default;
 
+	uint64_t *modifiers;
+	unsigned int modifier_count;
+
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 
@@ -527,13 +544,14 @@  struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-__printf(8, 9)
+__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, ...);
 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 2d36538e4a17..6d9adbb46293 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -122,6 +122,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_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 55e301047b3e..47f0175e29c0 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -184,6 +184,8 @@  extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
 /* 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))
 
@@ -196,6 +198,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

Comments

On Tue, May 16, 2017 at 02:31:24PM -0700, Ben Widawsky wrote:
> This is the plumbing for supporting fb modifiers on planes. Modifiers
> have already been introduced to some extent, but this series will extend
> this to allow querying modifiers per plane. Based on this, the client to
> enable optimal modifications for framebuffers.
> 
> This patch simply allows the DRM drivers to initialize their list of
> supported modifiers upon initializing the plane.
> 
> v2: A minor addition from Daniel
> 
> v3: Updated commit message
> s/INVALID/DRM_FORMAT_MOD_INVALID (Liviu)
> Remove some excess newlines (Liviu)
> Update comment for > 64 modifiers (Liviu)
> 
> Cc: Liviu Dudau <Liviu.Dudau@arm.com>
> Reviewed-by: Daniel Stone <daniels@collabora.com> (v2)
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

Minor nits, see below, but otherwise:

Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com>

Thanks,
Liviu

> ---
>  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_modeset_helper.c            |  1 +
>  drivers/gpu/drm/drm_plane.c                     | 35 ++++++++++++++++++++++++-
>  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            |  5 +++-
>  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       |  4 +--
>  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/qxl/qxl_display.c               |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +--
>  drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  4 +--
>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +--
>  drivers/gpu/drm/sti/sti_cursor.c                |  2 +-
>  drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
>  drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
>  drivers/gpu/drm/sun4i/sun4i_layer.c             |  2 +-
>  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/vmwgfx/vmwgfx_ldu.c             |  4 +--
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c            |  4 +--
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c            |  4 +--
>  drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
>  include/drm/drm_plane.h                         | 20 +++++++++++++-
>  include/drm/drm_simple_kms_helper.h             |  1 +
>  include/uapi/drm/drm_fourcc.h                   | 11 ++++++++
>  41 files changed, 126 insertions(+), 46 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 798a3cc480a2..0caa03ae8708 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -303,6 +303,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 814fda23cead..b156610c68a5 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -400,7 +400,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 4fe19fde84f9..ea48ef88f0e4 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -1269,6 +1269,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 424e465ff407..0054144287ae 100644
> --- a/drivers/gpu/drm/armada/armada_overlay.c
> +++ b/drivers/gpu/drm/armada/armada_overlay.c
> @@ -460,6 +460,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 29cc10d053eb..b5c6cf2d8c36 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> @@ -1058,7 +1058,9 @@ static int 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 ret;
>  
> 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 fedd4d60d9cd..20203871e06d 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -70,6 +70,8 @@ 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
> + *                    DRM_FORMAT_MOD_INVALID
>   * @type: type of plane (overlay, primary, cursor)
>   * @name: printf style format string for the plane name, or NULL for default name
>   *
> @@ -82,10 +84,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_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
> @@ -105,6 +109,30 @@ 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. Each

Kernel's style asks for multi-line comments to start with an empty /* line

> +	 * format is encoded as a bit and the current code only supports a u64.
> +	 */
> +	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 +145,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]));

I'm still worried that we can reach the memcpy with a NULL format_modifiers and we are opening
a security hole here.

>  	plane->possible_crtcs = possible_crtcs;
>  	plane->type = type;
>  
> @@ -205,7 +236,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 +256,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));
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index e084f9f8ca66..949f0ab0e267 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 59542bddc980..339e914cbaa3 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 c96c228a9898..1acb8af12246 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> @@ -909,7 +909,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 3617927af269..9dd67d51e7c9 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13594,18 +13594,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)
> @@ -13776,7 +13779,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 f7d431427115..053802dd08c1 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -1165,13 +1165,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 d63e853a0300..6c708c3b1cdc 100644
> --- a/drivers/gpu/drm/imx/ipuv3-plane.c
> +++ b/drivers/gpu/drm/imx/ipuv3-plane.c
> @@ -718,8 +718,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 a32d3b6e2e12..17e96fa47868 100644
> --- a/drivers/gpu/drm/meson/meson_plane.c
> +++ b/drivers/gpu/drm/meson/meson_plane.c
> @@ -223,6 +223,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 a38c5fe6cc19..a815bc0e78d1 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> @@ -1140,12 +1140,12 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
>  		ret = drm_universal_plane_init(dev, plane, 0xff,
>  				&mdp5_cursor_plane_funcs,
>  				mdp5_plane->formats, mdp5_plane->nformats,
> -				type, NULL);
> +				NULL, type, NULL);
>  	else
>  		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 d1b9c34c7c00..3ee3784a54f4 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -190,7 +190,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 0e58537352fe..dde71be463f8 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -1084,8 +1084,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 9168154d749e..9b8341d77468 100644
> --- a/drivers/gpu/drm/omapdrm/omap_plane.c
> +++ b/drivers/gpu/drm/omapdrm/omap_plane.c
> @@ -370,7 +370,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/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 058340a002c2..fcf1d2034449 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -788,7 +788,7 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
>  
>  	err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs,
>  				       funcs, formats, num_formats,
> -				       type, NULL);
> +				       NULL, type, NULL);
>  	if (err)
>  		goto free_plane;
>  
> 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 b0ff304ce3dc..e0c054f9b57a 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> @@ -368,8 +368,8 @@ 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 3f7a82d1e095..d0cf57de9afc 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -1280,7 +1280,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);
> @@ -1319,7 +1319,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..97c25e204bf4 100644
> --- a/drivers/gpu/drm/sti/sti_cursor.c
> +++ b/drivers/gpu/drm/sti/sti_cursor.c
> @@ -393,7 +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),
> -				       DRM_PLANE_TYPE_CURSOR, NULL);
> +				       NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (res) {
>  		DRM_ERROR("Failed to initialize universal plane\n");
>  		goto err_plane;
> diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
> index 88f16cdf6a4b..70391603c12d 100644
> --- a/drivers/gpu/drm/sti/sti_gdp.c
> +++ b/drivers/gpu/drm/sti/sti_gdp.c
> @@ -932,7 +932,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 66f843148ef7..9a1ff352820d 100644
> --- a/drivers/gpu/drm/sti/sti_hqvdp.c
> +++ b/drivers/gpu/drm/sti/sti_hqvdp.c
> @@ -1296,7 +1296,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 f26bde5b9117..2d9f8d01ac2e 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -115,7 +115,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  	ret = drm_universal_plane_init(drm, &layer->plane, 0,
>  				       &sun4i_backend_layer_funcs,
>  				       plane->formats, plane->nformats,
> -				       plane->type, NULL);
> +				       NULL, plane->type, NULL);
>  	if (ret) {
>  		dev_err(drm->dev, "Couldn't initialize layer\n");
>  		return ERR_PTR(ret);
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index 95b373f739f2..0380edd054ac 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 d34cd5393a9b..74b5e7afd6e9 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, 0,
>  				       &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 adcdbd0abef6..71ba455af915 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_plane.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
> @@ -298,7 +298,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/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index d3987bcf53f8..6f0bf6f9c6f8 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -439,7 +439,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  				       0, &vmw_ldu_plane_funcs,
>  				       vmw_primary_plane_formats,
>  				       ARRAY_SIZE(vmw_primary_plane_formats),
> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize primary plane");
>  		goto err_free;
> @@ -454,7 +454,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  			0, &vmw_ldu_cursor_funcs,
>  			vmw_cursor_plane_formats,
>  			ARRAY_SIZE(vmw_cursor_plane_formats),
> -			DRM_PLANE_TYPE_CURSOR, NULL);
> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize cursor plane");
>  		drm_plane_cleanup(&ldu->base.primary);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index 8d7dc9def7c2..42780c9cb90f 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -622,7 +622,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  				       0, &vmw_sou_plane_funcs,
>  				       vmw_primary_plane_formats,
>  				       ARRAY_SIZE(vmw_primary_plane_formats),
> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize primary plane");
>  		goto err_free;
> @@ -637,7 +637,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  			0, &vmw_sou_cursor_funcs,
>  			vmw_cursor_plane_formats,
>  			ARRAY_SIZE(vmw_cursor_plane_formats),
> -			DRM_PLANE_TYPE_CURSOR, NULL);
> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize cursor plane");
>  		drm_plane_cleanup(&sou->base.primary);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index bad31bdf09b6..f18fb966ce9c 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -1456,7 +1456,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  				       0, &vmw_stdu_plane_funcs,
>  				       vmw_primary_plane_formats,
>  				       ARRAY_SIZE(vmw_primary_plane_formats),
> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize primary plane");
>  		goto err_free;
> @@ -1471,7 +1471,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  			0, &vmw_stdu_cursor_funcs,
>  			vmw_cursor_plane_formats,
>  			ARRAY_SIZE(vmw_cursor_plane_formats),
> -			DRM_PLANE_TYPE_CURSOR, NULL);
> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize cursor plane");
>  		drm_plane_cleanup(&stdu->base.primary);
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index d646ac931663..ea29fee01f7d 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -539,7 +539,7 @@ int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
>  
>  	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 ret;
> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index 9ab3e7044812..2db5eed53d7b 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -392,6 +392,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).
> +	 *

Add a "Returns:" line here in the comment to match the style of the file's comments.

> +	 * 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);
>  };
>  
>  /**
> @@ -487,6 +501,9 @@ struct drm_plane {
>  	unsigned int format_count;
>  	bool format_default;
>  
> +	uint64_t *modifiers;
> +	unsigned int modifier_count;
> +
>  	struct drm_crtc *crtc;
>  	struct drm_framebuffer *fb;
>  
> @@ -527,13 +544,14 @@ struct drm_plane {
>  
>  #define obj_to_plane(x) container_of(x, struct drm_plane, base)
>  
> -__printf(8, 9)
> +__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, ...);
>  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 2d36538e4a17..6d9adbb46293 100644
> --- a/include/drm/drm_simple_kms_helper.h
> +++ b/include/drm/drm_simple_kms_helper.h
> @@ -122,6 +122,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_fourcc.h b/include/uapi/drm/drm_fourcc.h
> index 55e301047b3e..47f0175e29c0 100644
> --- a/include/uapi/drm/drm_fourcc.h
> +++ b/include/uapi/drm/drm_fourcc.h
> @@ -184,6 +184,8 @@ extern "C" {
>  #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
>  /* 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))
>  
> @@ -196,6 +198,15 @@ extern "C" {
>   */
>  
>  /*
> + * Invalid Modifier
> + *
> + * This modifier can be used as a sentinel to terminate list, or to initialize a

s/terminate list/terminate the format modifiers list/



> + * 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
> -- 
> 2.13.0
>
On 17-05-17 11:17:57, Liviu Dudau wrote:
>On Tue, May 16, 2017 at 02:31:24PM -0700, Ben Widawsky wrote:
>> This is the plumbing for supporting fb modifiers on planes. Modifiers
>> have already been introduced to some extent, but this series will extend
>> this to allow querying modifiers per plane. Based on this, the client to
>> enable optimal modifications for framebuffers.
>>
>> This patch simply allows the DRM drivers to initialize their list of
>> supported modifiers upon initializing the plane.
>>
>> v2: A minor addition from Daniel
>>
>> v3: Updated commit message
>> s/INVALID/DRM_FORMAT_MOD_INVALID (Liviu)
>> Remove some excess newlines (Liviu)
>> Update comment for > 64 modifiers (Liviu)
>>
>> Cc: Liviu Dudau <Liviu.Dudau@arm.com>
>> Reviewed-by: Daniel Stone <daniels@collabora.com> (v2)
>> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
>
>Minor nits, see below, but otherwise:
>
>Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com>
>
>Thanks,
>Liviu
>

Thank you. I took them all but the memcpy change, which I'm pretty sure is okay.
Take a quick look again and let me know.

>> ---
>>  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_modeset_helper.c            |  1 +
>>  drivers/gpu/drm/drm_plane.c                     | 35 ++++++++++++++++++++++++-
>>  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            |  5 +++-
>>  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       |  4 +--
>>  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/qxl/qxl_display.c               |  2 +-
>>  drivers/gpu/drm/rcar-du/rcar_du_plane.c         |  4 +--
>>  drivers/gpu/drm/rcar-du/rcar_du_vsp.c           |  4 +--
>>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c     |  4 +--
>>  drivers/gpu/drm/sti/sti_cursor.c                |  2 +-
>>  drivers/gpu/drm/sti/sti_gdp.c                   |  2 +-
>>  drivers/gpu/drm/sti/sti_hqvdp.c                 |  2 +-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c             |  2 +-
>>  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/vmwgfx/vmwgfx_ldu.c             |  4 +--
>>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c            |  4 +--
>>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c            |  4 +--
>>  drivers/gpu/drm/zte/zx_plane.c                  |  2 +-
>>  include/drm/drm_plane.h                         | 20 +++++++++++++-
>>  include/drm/drm_simple_kms_helper.h             |  1 +
>>  include/uapi/drm/drm_fourcc.h                   | 11 ++++++++
>>  41 files changed, 126 insertions(+), 46 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 798a3cc480a2..0caa03ae8708 100644
>> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
>> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
>> @@ -303,6 +303,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 814fda23cead..b156610c68a5 100644
>> --- a/drivers/gpu/drm/arm/malidp_planes.c
>> +++ b/drivers/gpu/drm/arm/malidp_planes.c
>> @@ -400,7 +400,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 4fe19fde84f9..ea48ef88f0e4 100644
>> --- a/drivers/gpu/drm/armada/armada_crtc.c
>> +++ b/drivers/gpu/drm/armada/armada_crtc.c
>> @@ -1269,6 +1269,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 424e465ff407..0054144287ae 100644
>> --- a/drivers/gpu/drm/armada/armada_overlay.c
>> +++ b/drivers/gpu/drm/armada/armada_overlay.c
>> @@ -460,6 +460,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 29cc10d053eb..b5c6cf2d8c36 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
>> @@ -1058,7 +1058,9 @@ static int 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 ret;
>>
>> 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 fedd4d60d9cd..20203871e06d 100644
>> --- a/drivers/gpu/drm/drm_plane.c
>> +++ b/drivers/gpu/drm/drm_plane.c
>> @@ -70,6 +70,8 @@ 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
>> + *                    DRM_FORMAT_MOD_INVALID
>>   * @type: type of plane (overlay, primary, cursor)
>>   * @name: printf style format string for the plane name, or NULL for default name
>>   *
>> @@ -82,10 +84,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_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
>> @@ -105,6 +109,30 @@ 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. Each
>
>Kernel's style asks for multi-line comments to start with an empty /* line
>

Okay, fine. I'm not the only one doing this in this file :-)

>> +	 * format is encoded as a bit and the current code only supports a u64.
>> +	 */
>> +	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 +145,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]));
>
>I'm still worried that we can reach the memcpy with a NULL format_modifiers and we are opening
>a security hole here.
>

I didn't notice your feedback here before, I apologize. I'm pretty certain you
can't get here with !format_modifiers (well you can, but then the 'n' for memcpy
will be 0). format_modifier_count is only !0 if format_modifiers is !NULL.

>>  	plane->possible_crtcs = possible_crtcs;
>>  	plane->type = type;
>>
>> @@ -205,7 +236,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 +256,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));
>> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
>> index e084f9f8ca66..949f0ab0e267 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 59542bddc980..339e914cbaa3 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 c96c228a9898..1acb8af12246 100644
>> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
>> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
>> @@ -909,7 +909,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 3617927af269..9dd67d51e7c9 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -13594,18 +13594,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)
>> @@ -13776,7 +13779,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 f7d431427115..053802dd08c1 100644
>> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> @@ -1165,13 +1165,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 d63e853a0300..6c708c3b1cdc 100644
>> --- a/drivers/gpu/drm/imx/ipuv3-plane.c
>> +++ b/drivers/gpu/drm/imx/ipuv3-plane.c
>> @@ -718,8 +718,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 a32d3b6e2e12..17e96fa47868 100644
>> --- a/drivers/gpu/drm/meson/meson_plane.c
>> +++ b/drivers/gpu/drm/meson/meson_plane.c
>> @@ -223,6 +223,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 a38c5fe6cc19..a815bc0e78d1 100644
>> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
>> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
>> @@ -1140,12 +1140,12 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
>>  		ret = drm_universal_plane_init(dev, plane, 0xff,
>>  				&mdp5_cursor_plane_funcs,
>>  				mdp5_plane->formats, mdp5_plane->nformats,
>> -				type, NULL);
>> +				NULL, type, NULL);
>>  	else
>>  		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 d1b9c34c7c00..3ee3784a54f4 100644
>> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>> @@ -190,7 +190,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 0e58537352fe..dde71be463f8 100644
>> --- a/drivers/gpu/drm/nouveau/nv50_display.c
>> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
>> @@ -1084,8 +1084,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 9168154d749e..9b8341d77468 100644
>> --- a/drivers/gpu/drm/omapdrm/omap_plane.c
>> +++ b/drivers/gpu/drm/omapdrm/omap_plane.c
>> @@ -370,7 +370,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/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
>> index 058340a002c2..fcf1d2034449 100644
>> --- a/drivers/gpu/drm/qxl/qxl_display.c
>> +++ b/drivers/gpu/drm/qxl/qxl_display.c
>> @@ -788,7 +788,7 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
>>
>>  	err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs,
>>  				       funcs, formats, num_formats,
>> -				       type, NULL);
>> +				       NULL, type, NULL);
>>  	if (err)
>>  		goto free_plane;
>>
>> 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 b0ff304ce3dc..e0c054f9b57a 100644
>> --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
>> @@ -368,8 +368,8 @@ 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 3f7a82d1e095..d0cf57de9afc 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -1280,7 +1280,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);
>> @@ -1319,7 +1319,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..97c25e204bf4 100644
>> --- a/drivers/gpu/drm/sti/sti_cursor.c
>> +++ b/drivers/gpu/drm/sti/sti_cursor.c
>> @@ -393,7 +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),
>> -				       DRM_PLANE_TYPE_CURSOR, NULL);
>> +				       NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>>  	if (res) {
>>  		DRM_ERROR("Failed to initialize universal plane\n");
>>  		goto err_plane;
>> diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
>> index 88f16cdf6a4b..70391603c12d 100644
>> --- a/drivers/gpu/drm/sti/sti_gdp.c
>> +++ b/drivers/gpu/drm/sti/sti_gdp.c
>> @@ -932,7 +932,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 66f843148ef7..9a1ff352820d 100644
>> --- a/drivers/gpu/drm/sti/sti_hqvdp.c
>> +++ b/drivers/gpu/drm/sti/sti_hqvdp.c
>> @@ -1296,7 +1296,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 f26bde5b9117..2d9f8d01ac2e 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>> @@ -115,7 +115,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>  	ret = drm_universal_plane_init(drm, &layer->plane, 0,
>>  				       &sun4i_backend_layer_funcs,
>>  				       plane->formats, plane->nformats,
>> -				       plane->type, NULL);
>> +				       NULL, plane->type, NULL);
>>  	if (ret) {
>>  		dev_err(drm->dev, "Couldn't initialize layer\n");
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
>> index 95b373f739f2..0380edd054ac 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 d34cd5393a9b..74b5e7afd6e9 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, 0,
>>  				       &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 adcdbd0abef6..71ba455af915 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_plane.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
>> @@ -298,7 +298,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/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
>> index d3987bcf53f8..6f0bf6f9c6f8 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
>> @@ -439,7 +439,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>>  				       0, &vmw_ldu_plane_funcs,
>>  				       vmw_primary_plane_formats,
>>  				       ARRAY_SIZE(vmw_primary_plane_formats),
>> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
>> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize primary plane");
>>  		goto err_free;
>> @@ -454,7 +454,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>>  			0, &vmw_ldu_cursor_funcs,
>>  			vmw_cursor_plane_formats,
>>  			ARRAY_SIZE(vmw_cursor_plane_formats),
>> -			DRM_PLANE_TYPE_CURSOR, NULL);
>> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize cursor plane");
>>  		drm_plane_cleanup(&ldu->base.primary);
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
>> index 8d7dc9def7c2..42780c9cb90f 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
>> @@ -622,7 +622,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>>  				       0, &vmw_sou_plane_funcs,
>>  				       vmw_primary_plane_formats,
>>  				       ARRAY_SIZE(vmw_primary_plane_formats),
>> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
>> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize primary plane");
>>  		goto err_free;
>> @@ -637,7 +637,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>>  			0, &vmw_sou_cursor_funcs,
>>  			vmw_cursor_plane_formats,
>>  			ARRAY_SIZE(vmw_cursor_plane_formats),
>> -			DRM_PLANE_TYPE_CURSOR, NULL);
>> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize cursor plane");
>>  		drm_plane_cleanup(&sou->base.primary);
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
>> index bad31bdf09b6..f18fb966ce9c 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
>> @@ -1456,7 +1456,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>>  				       0, &vmw_stdu_plane_funcs,
>>  				       vmw_primary_plane_formats,
>>  				       ARRAY_SIZE(vmw_primary_plane_formats),
>> -				       DRM_PLANE_TYPE_PRIMARY, NULL);
>> +				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize primary plane");
>>  		goto err_free;
>> @@ -1471,7 +1471,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>>  			0, &vmw_stdu_cursor_funcs,
>>  			vmw_cursor_plane_formats,
>>  			ARRAY_SIZE(vmw_cursor_plane_formats),
>> -			DRM_PLANE_TYPE_CURSOR, NULL);
>> +			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
>>  	if (ret) {
>>  		DRM_ERROR("Failed to initialize cursor plane");
>>  		drm_plane_cleanup(&stdu->base.primary);
>> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
>> index d646ac931663..ea29fee01f7d 100644
>> --- a/drivers/gpu/drm/zte/zx_plane.c
>> +++ b/drivers/gpu/drm/zte/zx_plane.c
>> @@ -539,7 +539,7 @@ int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
>>
>>  	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 ret;
>> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
>> index 9ab3e7044812..2db5eed53d7b 100644
>> --- a/include/drm/drm_plane.h
>> +++ b/include/drm/drm_plane.h
>> @@ -392,6 +392,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).
>> +	 *
>
>Add a "Returns:" line here in the comment to match the style of the file's comments.
>

Got it.

>> +	 * 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);
>>  };
>>
>>  /**
>> @@ -487,6 +501,9 @@ struct drm_plane {
>>  	unsigned int format_count;
>>  	bool format_default;
>>
>> +	uint64_t *modifiers;
>> +	unsigned int modifier_count;
>> +
>>  	struct drm_crtc *crtc;
>>  	struct drm_framebuffer *fb;
>>
>> @@ -527,13 +544,14 @@ struct drm_plane {
>>
>>  #define obj_to_plane(x) container_of(x, struct drm_plane, base)
>>
>> -__printf(8, 9)
>> +__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, ...);
>>  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 2d36538e4a17..6d9adbb46293 100644
>> --- a/include/drm/drm_simple_kms_helper.h
>> +++ b/include/drm/drm_simple_kms_helper.h
>> @@ -122,6 +122,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_fourcc.h b/include/uapi/drm/drm_fourcc.h
>> index 55e301047b3e..47f0175e29c0 100644
>> --- a/include/uapi/drm/drm_fourcc.h
>> +++ b/include/uapi/drm/drm_fourcc.h
>> @@ -184,6 +184,8 @@ extern "C" {
>>  #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
>>  /* 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))
>>
>> @@ -196,6 +198,15 @@ extern "C" {
>>   */
>>
>>  /*
>> + * Invalid Modifier
>> + *
>> + * This modifier can be used as a sentinel to terminate list, or to initialize a
>
>s/terminate list/terminate the format modifiers list/
>
>

Got it.

>
>> + * 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
>> --
>> 2.13.0
>>
>
>-- 
>====================
>| I would like to |
>| fix the world,  |
>| but they're not |
>| giving me the   |
> \ source code!  /
>  ---------------
>    ¯\_(ツ)_/¯
On Wed, May 17, 2017 at 05:26:14PM -0700, Ben Widawsky wrote:
> On 17-05-17 11:17:57, Liviu Dudau wrote:
> > On Tue, May 16, 2017 at 02:31:24PM -0700, Ben Widawsky wrote:
> > > This is the plumbing for supporting fb modifiers on planes. Modifiers
> > > have already been introduced to some extent, but this series will extend
> > > this to allow querying modifiers per plane. Based on this, the client to
> > > enable optimal modifications for framebuffers.
> > > 
> > > This patch simply allows the DRM drivers to initialize their list of
> > > supported modifiers upon initializing the plane.
> > > 
> > > v2: A minor addition from Daniel
> > > 
> > > v3: Updated commit message
> > > s/INVALID/DRM_FORMAT_MOD_INVALID (Liviu)
> > > Remove some excess newlines (Liviu)
> > > Update comment for > 64 modifiers (Liviu)
> > > 
> > > Cc: Liviu Dudau <Liviu.Dudau@arm.com>
> > > Reviewed-by: Daniel Stone <daniels@collabora.com> (v2)
> > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > 
> > Minor nits, see below, but otherwise:
> > 
> > Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com>
> > 
> > Thanks,
> > Liviu
> > 
> 
> Thank you. I took them all but the memcpy change, which I'm pretty sure is okay.
> Take a quick look again and let me know.

[snip]
> 
> > > +	 * format is encoded as a bit and the current code only supports a u64.
> > > +	 */
> > > +	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 +145,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]));
> > 
> > I'm still worried that we can reach the memcpy with a NULL format_modifiers and we are opening
> > a security hole here.
> > 
> 
> I didn't notice your feedback here before, I apologize. I'm pretty certain you
> can't get here with !format_modifiers (well you can, but then the 'n' for memcpy
> will be 0). format_modifier_count is only !0 if format_modifiers is !NULL.

That is a valid point. It then makes me ask why we even go through the dance of allocating
a 0 array for plane->modifiers, can we not skip the whole thing around plane->modifiers if
format_modifiers is NULL?

[snip]

> -- 
> Ben Widawsky, Intel Open Source Technology Center

Thanks for the effort,
Liviu