Originally based off of a patch by Kristian.

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

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

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

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

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

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

v4:
  - Add drivers/gpu/drm/qxl/

Cc: Rob Clark <robdcl...@gmail.com>
Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
Cc: Daniel Stone <dan...@fooishbar.org>
Cc: "Kristian H. Kristensen" <hoegsb...@gmail.com>
References: https://patchwork.kernel.org/patch/9482393/
Signed-off-by: Ben Widawsky <b...@bwidawsk.net>
---
 drivers/gpu/drm/arc/arcpgu_crtc.c               |  1 +
 drivers/gpu/drm/arm/hdlcd_crtc.c                |  1 +
 drivers/gpu/drm/arm/malidp_planes.c             |  2 +-
 drivers/gpu/drm/armada/armada_crtc.c            |  1 +
 drivers/gpu/drm/armada/armada_overlay.c         |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |  4 +-
 drivers/gpu/drm/drm_ioctl.c                     |  2 +-
 drivers/gpu/drm/drm_modeset_helper.c            |  1 +
 drivers/gpu/drm/drm_plane.c                     | 67 ++++++++++++++++++++++++-
 drivers/gpu/drm/drm_simple_kms_helper.c         |  3 ++
 drivers/gpu/drm/exynos/exynos_drm_plane.c       |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c     |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  |  1 +
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c            |  7 ++-
 drivers/gpu/drm/i915/intel_sprite.c             |  4 +-
 drivers/gpu/drm/imx/ipuv3-plane.c               |  4 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c        |  2 +-
 drivers/gpu/drm/meson/meson_plane.c             |  1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c       |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c       |  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/zte/zx_plane.c                  |  2 +-
 include/drm/drm_plane.h                         | 21 +++++++-
 include/drm/drm_simple_kms_helper.h             |  1 +
 include/uapi/drm/drm.h                          |  1 +
 include/uapi/drm/drm_fourcc.h                   | 11 ++++
 include/uapi/drm/drm_mode.h                     | 44 ++++++++++++++++
 41 files changed, 200 insertions(+), 42 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 d5aec082294c..9b27d8555392 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -328,7 +328,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 1341e0b9368a..b3deabf4f502 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1268,6 +1268,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, 
struct device *dev,
                                       &armada_primary_plane_funcs,
                                       armada_primary_formats,
                                       ARRAY_SIZE(armada_primary_formats),
+                                      NULL,
                                       DRM_PLANE_TYPE_PRIMARY, NULL);
        if (ret) {
                kfree(primary);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c 
b/drivers/gpu/drm/armada/armada_overlay.c
index 34cb73d0db77..6a1ca8aa8e16 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -458,6 +458,7 @@ int armada_overlay_plane_create(struct drm_device *dev, 
unsigned long crtcs)
                                       &armada_ovl_plane_funcs,
                                       armada_ovl_formats,
                                       ARRAY_SIZE(armada_ovl_formats),
+                                      NULL,
                                       DRM_PLANE_TYPE_OVERLAY, NULL);
        if (ret) {
                kfree(dplane);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c 
b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 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_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a7c61c23685a..c820d99d9231 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -614,7 +614,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, 
DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, 
DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, 
DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE2, drm_mode_getplane, 
DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, 
DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_modeset_helper.c 
b/drivers/gpu/drm/drm_modeset_helper.c
index 2b33825f2f93..9cb1eede0b4d 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -124,6 +124,7 @@ static struct drm_plane *create_primary_plane(struct 
drm_device *dev)
                                       &drm_primary_helper_funcs,
                                       safe_modeset_formats,
                                       ARRAY_SIZE(safe_modeset_formats),
+                                      NULL,
                                       DRM_PLANE_TYPE_PRIMARY, NULL);
        if (ret) {
                kfree(primary);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index a22e76837065..33a7d3d53d4a 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -70,6 +70,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
  * @funcs: callbacks for the new plane
  * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
+ * @format_modifiers: array of struct drm_format modifiers terminated by 
INVALID
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default 
name
  *
@@ -82,10 +83,12 @@ int drm_universal_plane_init(struct drm_device *dev, struct 
drm_plane *plane,
                             uint32_t possible_crtcs,
                             const struct drm_plane_funcs *funcs,
                             const uint32_t *formats, unsigned int format_count,
+                            const uint64_t *format_modifiers,
                             enum drm_plane_type type,
                             const char *name, ...)
 {
        struct drm_mode_config *config = &dev->mode_config;
+       unsigned int format_modifier_count = 0;
        int ret;
 
        ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +108,28 @@ int drm_universal_plane_init(struct drm_device *dev, 
struct drm_plane *plane,
                return -ENOMEM;
        }
 
+       /* First driver to need more than 64 formats needs to fix this */
+       if (WARN_ON(format_count > 64))
+               return -EINVAL;
+
+       if (format_modifiers) {
+               const uint64_t *temp_modifiers = format_modifiers;
+               while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
+                       format_modifier_count++;
+       }
+
+       plane->modifier_count = format_modifier_count;
+       plane->modifiers = kmalloc_array(format_modifier_count,
+                                        sizeof(format_modifiers[0]),
+                                        GFP_KERNEL);
+
+       if (format_modifier_count && !plane->modifiers) {
+               DRM_DEBUG_KMS("out of memory when allocating plane\n");
+               kfree(plane->format_types);
+               drm_mode_object_unregister(dev, &plane->base);
+               return -ENOMEM;
+       }
+
        if (name) {
                va_list ap;
 
@@ -117,12 +142,15 @@ int drm_universal_plane_init(struct drm_device *dev, 
struct drm_plane *plane,
        }
        if (!plane->name) {
                kfree(plane->format_types);
+               kfree(plane->modifiers);
                drm_mode_object_unregister(dev, &plane->base);
                return -ENOMEM;
        }
 
        memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
        plane->format_count = format_count;
+       memcpy(plane->modifiers, format_modifiers,
+              format_modifier_count * sizeof(format_modifiers[0]));
        plane->possible_crtcs = possible_crtcs;
        plane->type = type;
 
@@ -205,7 +233,8 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
 
        type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
        return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-                                       formats, format_count, type, NULL);
+                                       formats, format_count,
+                                       NULL, type, NULL);
 }
 EXPORT_SYMBOL(drm_plane_init);
 
@@ -224,6 +253,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
        drm_modeset_lock_fini(&plane->mutex);
 
        kfree(plane->format_types);
+       kfree(plane->modifiers);
        drm_mode_object_unregister(dev, &plane->base);
 
        BUG_ON(list_empty(&plane->head));
@@ -380,12 +410,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void 
*data,
 int drm_mode_getplane(struct drm_device *dev, void *data,
                      struct drm_file *file_priv)
 {
-       struct drm_mode_get_plane *plane_resp = data;
+       struct drm_mode_get_plane2 *plane_resp = data;
        struct drm_plane *plane;
        uint32_t __user *format_ptr;
+       struct drm_format_modifier __user *modifier_ptr;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
+       if (plane_resp->flags)
+               return -EINVAL;
 
        plane = drm_plane_find(dev, plane_resp->plane_id);
        if (!plane)
@@ -426,6 +459,36 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
        }
        plane_resp->count_format_types = plane->format_count;
 
+       if (plane->modifier_count &&
+           plane_resp->count_format_modifiers >= plane->modifier_count) {
+               struct drm_format_modifier mod = {0};
+               int i;
+
+               modifier_ptr = (struct drm_format_modifier __user *)
+                       (unsigned long)plane_resp->format_modifier_ptr;
+
+               /* Build the mask for each modifier */
+               for (i = 0; i < plane->modifier_count; i++) {
+                       int j;
+                       mod.modifier = plane->modifiers[i];
+                       for (j = 0; j < plane->format_count; j++) {
+                               if (plane->funcs->format_mod_supported &&
+                                   plane->funcs->format_mod_supported(plane,
+                                                                      
plane->format_types[j],
+                                                                      
plane->modifiers[i])) {
+                                       mod.formats |= 1 << j;
+                               }
+                       }
+
+                       if (copy_to_user(modifier_ptr, &mod, sizeof(mod)))
+                               return -EFAULT;
+
+                       modifier_ptr++;
+               }
+       }
+
+       plane_resp->count_format_modifiers = plane->modifier_count;
+
        return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c 
b/drivers/gpu/drm/drm_simple_kms_helper.c
index 16789faa9291..b107a83b7c1a 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 696d106461f8..802a8449c5d3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13587,6 +13587,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                                              src_x, src_y, src_w, src_h);
 }
 
+
+
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
        .update_plane = intel_legacy_cursor_update,
        .disable_plane = drm_atomic_helper_disable_plane,
@@ -13671,18 +13673,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)
@@ -13847,7 +13852,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 12e33bc149e4..9f2bdefdc690 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1186,13 +1186,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 0ffb8affef35..8ff6f7eafc50 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -1000,12 +1000,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 418872b493a3..9188536f2e93 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1086,8 +1086,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 386d90af70f7..a98ab2c7bc32 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -360,7 +360,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 2151e1cee4b4..9669f18a9ee9 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 86279f5022c2..2db412d8be28 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -930,7 +930,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 5d53c977bca5..1139050f8979 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -117,7 +117,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct 
drm_device *drm,
        ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
                                       &sun4i_backend_layer_funcs,
                                       plane->formats, plane->nformats,
-                                      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 0db5d5a8d3b9..e53d19abc174 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 0f4564beb017..dadab618e67b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -859,7 +859,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 1ff9c64c9ec0..28da79211e8e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -226,7 +226,7 @@ struct drm_plane *virtio_gpu_plane_init(struct 
virtio_gpu_device *vgdev,
        ret = drm_universal_plane_init(dev, plane, 1 << index,
                                       &virtio_gpu_plane_funcs,
                                       formats, nformats,
-                                      type, NULL);
+                                      NULL, type, NULL);
        if (ret)
                goto err_plane_init;
 
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
index 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 31da9f0c4ad2..3bbfc69739ce 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -389,6 +389,20 @@ struct drm_plane_funcs {
         */
        void (*atomic_print_state)(struct drm_printer *p,
                                   const struct drm_plane_state *state);
+
+       /**
+        * @format_mod_supported:
+        *
+        * This optional hook is used for the DRM to determine if the given
+        * format/modifier combination is valid for the plane. This allows the
+        * DRM to generate the correct format bitmask (which formats apply to
+        * which modifier).
+        *
+        * True if the given modifier is valid for that format on the plane.
+        * False otherwise.
+        */
+       bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,
+                                    uint64_t modifier);
 };
 
 /**
@@ -483,6 +497,10 @@ struct drm_plane {
        unsigned int format_count;
        bool format_default;
 
+       uint32_t *formats;
+       uint64_t *modifiers;
+       unsigned int modifier_count;
+
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb;
 
@@ -510,13 +528,14 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-__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 fffbb95a0915..f136606e7c80 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.h b/include/uapi/drm/drm.h
index b2c52843bc70..487e0f17113f 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -805,6 +805,7 @@ extern "C" {
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct 
drm_mode_destroy_dumb)
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct 
drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE        DRM_IOWR(0xB6, struct 
drm_mode_get_plane)
+#define DRM_IOCTL_MODE_GETPLANE2       DRM_IOWR(0xB6, struct 
drm_mode_get_plane2)
 #define DRM_IOCTL_MODE_SETPLANE        DRM_IOWR(0xB7, struct 
drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2          DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES       DRM_IOWR(0xB9, struct 
drm_mode_obj_get_properties)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 995c8f9c692f..ddabbeeebdec 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
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 8c67fc03d53d..c4a6fdb9e714 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -213,6 +213,50 @@ struct drm_mode_get_plane {
        __u64 format_type_ptr;
 };
 
+struct drm_format_modifier {
+       /* Bitmask of formats in get_plane format list this info applies to. The
+        * offset allows a sliding window of which 64 formats (bits).
+        *
+        * Some examples:
+        * In today's world with < 65 formats, and formats 0, and 2 are
+        * supported
+        * 0x0000000000000005
+        *                  ^-offset = 0, formats = 5
+        *
+        * If the number formats grew to 128, and formats 98-102 are
+        * supported with the modifier:
+        *
+        * 0x0000003c00000000 0000000000000000
+        *                  ^
+        *                  |__offset = 64, formats = 0x3c00000000
+        *
+        */
+       uint64_t formats;
+       uint32_t offset;
+       uint32_t pad;
+
+       /* This modifier can be used with the format for this plane. */
+       uint64_t modifier;
+};
+
+struct drm_mode_get_plane2 {
+       __u32 plane_id;
+
+       __u32 crtc_id;
+       __u32 fb_id;
+
+       __u32 possible_crtcs;
+       __u32 gamma_size;
+
+       __u32 count_format_types;
+       __u64 format_type_ptr;
+
+       /* New in v2 */
+       __u32 flags;
+       __u32 count_format_modifiers;
+       __u64 format_modifier_ptr;
+};
+
 struct drm_mode_get_plane_res {
        __u64 plane_id_ptr;
        __u32 count_planes;
-- 
2.12.1

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

Reply via email to