drm: Plumb modifiers through plane init
authorBen Widawsky <ben@bwidawsk.net>
Mon, 24 Jul 2017 03:46:38 +0000 (20:46 -0700)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:52:03 +0000 (14:52 -0500)
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)

v4: Minor comment adjustments (Liviu)

v5: Some new platforms added due to rebase

v6: Add some missed plane inits (or maybe they're new - who knows at
this point) (Daniel)

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Daniel Stone <daniels@collabora.com> (v2)
Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Daniel Stone <daniels@collabora.com>
(cherry picked from commit e6fc3b68558e4c6d8d160b5daf2511b99afa8814)

Conflicts:
       drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
       drivers/gpu/drm/imx/dcss/dcss-plane.c
       drivers/gpu/drm/imx/dpu/dpu-plane.c
       drivers/gpu/drm/imx/ipuv3-plane.c
       drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
       drivers/gpu/drm/meson/meson_plane.c
       drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
       drivers/gpu/drm/mxsfb/mxsfb_drv.c
       drivers/gpu/drm/nouveau/nv50_display.c
       drivers/gpu/drm/omapdrm/omap_plane.c
       drivers/gpu/drm/pl111/pl111_display.c
       drivers/gpu/drm/qxl/qxl_display.c
       drivers/gpu/drm/stm/ltdc.c
       drivers/gpu/drm/sun4i/sun8i_layer.c
       drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
       drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
       drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
       drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
       drivers/gpu/drm/zte/zx_plane.c
       include/drm/drm_plane.h

35 files changed:
drivers/gpu/drm/arc/arcpgu_crtc.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_overlay.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/drm_modeset_helper.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/imx/dcss/dcss-plane.c
drivers/gpu/drm/imx/dpu/dpu-plane.c
drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/omapdrm/omap_plane.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/sti/sti_cursor.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_hqvdp.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/virtio/virtgpu_plane.c
include/drm/drm_plane.h
include/drm/drm_simple_kms_helper.h
include/uapi/drm/drm_fourcc.h

index 7130b04..1887bb2 100644 (file)
@@ -217,6 +217,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);
index 28341b3..9da37d3 100644 (file)
@@ -282,6 +282,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);
index 8b009b5..1b0305a 100644 (file)
@@ -246,7 +246,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;
 
index 3137adf..d022c34 100644 (file)
@@ -1210,6 +1210,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);
index 152b4e7..54f0323 100644 (file)
@@ -461,6 +461,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);
index 9d4c030..9c5907d 100644 (file)
@@ -1028,7 +1028,8 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
        ret = drm_universal_plane_init(dev, &plane->base, 0,
                                       &layer_plane_funcs,
                                       desc->formats->formats,
-                                      desc->formats->nformats, type, NULL);
+                                      desc->formats->nformats,
+                                      NULL, type, NULL);
        if (ret)
                return ERR_PTR(ret);
 
index 1d45738..5f7e926 100644 (file)
@@ -120,6 +120,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);
index e7f740c..5e47eb2 100644 (file)
@@ -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_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
@@ -105,6 +109,31 @@ 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 +146,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;
 
@@ -204,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);
 
@@ -222,6 +255,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
 
        drm_modeset_lock_all(dev);
        kfree(plane->format_types);
+       kfree(plane->modifiers);
        drm_mode_object_unregister(dev, &plane->base);
 
        BUG_ON(list_empty(&plane->head));
index 7bae08c..83ce9bf 100644 (file)
@@ -212,6 +212,7 @@ EXPORT_SYMBOL(drm_simple_display_pipe_detach_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
@@ -232,6 +233,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;
@@ -246,6 +248,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;
index c2f17f3..75d4928 100644 (file)
@@ -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;
index a99f488..c3c6f93 100644 (file)
@@ -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;
index 0f563c9..d159705 100644 (file)
@@ -915,7 +915,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;
index ab741eb..2b69e56 100644 (file)
@@ -14988,18 +14988,21 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
                ret = drm_universal_plane_init(dev, &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_INFO(dev)->gen >= 5 || IS_G4X(dev))
                ret = drm_universal_plane_init(dev, &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, &primary->base, 0,
                                               &intel_plane_funcs,
                                               intel_primary_formats, num_formats,
+                                              NULL,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane %c", plane_name(primary->plane));
        if (ret)
@@ -15158,7 +15161,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
                                       &intel_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;
index 9f41649..f23aaf7 100644 (file)
@@ -1153,13 +1153,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
                ret = drm_universal_plane_init(dev, &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, &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;
index f1902ef..e9a2ee1 100644 (file)
@@ -295,8 +295,8 @@ struct dcss_plane *dcss_plane_init(struct drm_device *drm,
 
        ret = drm_universal_plane_init(drm, &dcss_plane->base, possible_crtcs,
                                       &dcss_plane_funcs, dcss_common_formats,
-                                      ARRAY_SIZE(dcss_common_formats), type,
-                                      NULL);
+                                      ARRAY_SIZE(dcss_common_formats),
+                                      NULL, type, NULL);
        if (ret) {
                DRM_ERROR("failed to initialize plane\n");
                kfree(dcss_plane);
index 5156383..24f37d3 100644 (file)
@@ -652,8 +652,8 @@ struct dpu_plane *dpu_plane_init(struct drm_device *drm,
 
        ret = drm_universal_plane_init(drm, plane, possible_crtcs,
                                       &dpu_plane_funcs, dpu_common_formats,
-                                      ARRAY_SIZE(dpu_common_formats), type,
-                                      NULL);
+                                      ARRAY_SIZE(dpu_common_formats),
+                                      NULL, type, NULL);
        if (ret) {
                kfree(dpu_plane);
                return ERR_PTR(ret);
index d5864ed..52a975e 100644 (file)
@@ -483,8 +483,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);
index c461a23..c3e6d37 100644 (file)
@@ -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;
index 3903dbc..b58212c 100644 (file)
@@ -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;
 
index 83bf997..5363715 100644 (file)
@@ -901,7 +901,7 @@ struct drm_plane *mdp5_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, &mdp5_plane_funcs,
                                 mdp5_plane->formats, mdp5_plane->nformats,
-                                type, NULL);
+                                NULL, type, NULL);
        if (ret)
                goto fail;
 
index 02f6dcc..0f17c1e 100644 (file)
@@ -245,7 +245,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, mxsfb->devdata->num_formats,
+                       mxsfb_formats, mxsfb->devdata->num_formats, NULL,
                        mxsfb->connector);
        if (ret < 0) {
                dev_err(drm->dev, "Cannot setup simple display pipe\n");
index 66ac8c4..eb396d6 100644 (file)
@@ -371,7 +371,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
        ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1,
                                       &omap_plane_funcs, omap_plane->formats,
-                                      omap_plane->nformats, type, NULL);
+                                      omap_plane->nformats, NULL, type, NULL);
        if (ret < 0)
                goto error;
 
index a74f8ed..7635a87 100644 (file)
@@ -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;
 
index 83ebd16..58e9321 100644 (file)
@@ -364,8 +364,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;
 
index c7eba30..b7de9af 100644 (file)
@@ -1221,7 +1221,7 @@ static int vop_create_crtc(struct vop *vop)
                                               0, &vop_plane_funcs,
                                               win_data->phy->data_formats,
                                               win_data->phy->nformats,
-                                              win_data->type, NULL);
+                                              NULL, win_data->type, NULL);
                if (ret) {
                        DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
                                      ret);
@@ -1260,7 +1260,7 @@ static int vop_create_crtc(struct vop *vop)
                                               &vop_plane_funcs,
                                               win_data->phy->data_formats,
                                               win_data->phy->nformats,
-                                              win_data->type, NULL);
+                                              NULL, win_data->type, NULL);
                if (ret) {
                        DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
                                      ret);
index cca75bd..97c25e2 100644 (file)
@@ -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;
index 7fd496f..5ce8b7d 100644 (file)
@@ -923,7 +923,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;
index f88130f..8ea4223 100644 (file)
@@ -1277,7 +1277,7 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
                                       &sti_hqvdp_plane_helpers_funcs,
                                       hqvdp_supported_formats,
                                       ARRAY_SIZE(hqvdp_supported_formats),
-                                      DRM_PLANE_TYPE_OVERLAY, NULL);
+                                      NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
        if (res) {
                DRM_ERROR("Failed to initialize universal plane\n");
                return NULL;
index f0035bf..e3b44b2 100644 (file)
@@ -111,7 +111,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);
index 4010d69..e110b2e 100644 (file)
@@ -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);
index 1c29515..56267de 100644 (file)
@@ -884,7 +884,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
        ret = drm_universal_plane_init(dev, plane, 0xff,
                                       &vc4_plane_funcs,
                                       formats, num_formats,
-                                      type, NULL);
+                                      NULL, type, NULL);
 
        drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
 
index ba28c0f..11c0a5d 100644 (file)
@@ -225,7 +225,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
        ret = drm_universal_plane_init(dev, plane, 1 << index,
                                       &virtio_gpu_plane_funcs,
                                       formats, nformats,
-                                      type, NULL);
+                                      NULL, type, NULL);
        if (ret)
                goto err_plane_init;
 
index 5c08b0c..6359153 100644 (file)
@@ -323,6 +323,22 @@ struct drm_plane_funcs {
         * before data structures are torndown.
         */
        void (*early_unregister)(struct drm_plane *plane);
+
+       /**
+        * @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).
+        *
+        * Returns:
+        *
+        * 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);
 };
 
 /**
@@ -416,6 +432,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;
 
@@ -442,13 +461,14 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-extern __printf(8, 9)
+extern __printf(9, 10)
 int drm_universal_plane_init(struct drm_device *dev,
                             struct drm_plane *plane,
                             uint32_t possible_crtcs,
                             const struct drm_plane_funcs *funcs,
                             const uint32_t *formats,
                             unsigned int format_count,
+                            const uint64_t *format_modifiers,
                             enum drm_plane_type type,
                             const char *name, ...);
 extern int drm_plane_init(struct drm_device *dev,
index 01a8436..36d22de 100644 (file)
@@ -120,6 +120,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 */
index b8b74f8..0c8bc92 100644 (file)
@@ -165,6 +165,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_AMPHION  0x08
 /* 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))
 
@@ -176,6 +178,15 @@ extern "C" {
  * authoritative source for all of these.
  */
 
+/*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate the format modifiers
+ * 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
  *