drm: Plumb modifiers through plane init
authorBen Widawsky <ben@bwidawsk.net>
Mon, 24 Jul 2017 03:46:38 +0000 (20:46 -0700)
committerDaniel Stone <daniels@collabora.com>
Tue, 1 Aug 2017 16:50:06 +0000 (17:50 +0100)
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>
45 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/hibmc/hibmc_drm_de.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/ipuv3-plane.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/meson/meson_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/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/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/stm/ltdc.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun8i_layer.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/virtio/virtgpu_plane.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
include/drm/drm_simple_kms_helper.h
include/uapi/drm/drm_fourcc.h

index 1859dd3ad622db044ea51de19a50ee00b39441ae..799416651f2f0e10c307483c48460bbe07ce9f99 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 16e1e20cf04cf45ba5921715511d1babc9173c4a..72b22b805412b2cb19d8d90e85904be737ecf335 100644 (file)
@@ -315,6 +315,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) {
                return ERR_PTR(ret);
index 600fa7bd7f5201b451069dee8f21e9871cae70e3..60402e27882fafd1650b44735341052f99e2ee7b 100644 (file)
@@ -398,7 +398,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 1ffba91fbaae361ea9c813363d0a666c134373ce..1d01ad24fe520d6c149c28511a6c8e7ec7910b81 100644 (file)
@@ -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);
index 677b44f3534b9442c8aa31b131adf0b8dc4f1502..edc44910d79fc7c65bce893d31b2caf9ce1d34e4 100644 (file)
@@ -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);
index b5bd9b0052257c89ae640aacefc908515ab38c63..ba532bf101e0bc59b539cc0ce8834128c213c9b3 100644 (file)
@@ -1087,7 +1087,8 @@ 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;
 
index 2b33825f2f93138066b3593289bd076ad9f43409..9cb1eede0b4d9444a40e9b575b0e0184f4d2c9a5 100644 (file)
@@ -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);
index 5dc8c4350602a561fe4cfd77fce77e26770696fb..d3fc561d7b481446169d2ebe5f060963730d0296 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_add(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;
 
@@ -205,7 +237,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 +257,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));
index 39c203ad59db81731b21064ecc571caf520d6e02..dc9fd109de14f00db553b4b02a6bd882f08a94aa 100644 (file)
@@ -199,6 +199,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
@@ -219,6 +220,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;
@@ -233,6 +235,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 611b6fd65433d0a29a77c8549dcca47c0e4979a9..e5099bc9f21a0fcf23b57ded2671bdc40ec3ad9b 100644 (file)
@@ -283,7 +283,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 0a20723aa6e17194b08940beef9c211299a30455..9554b245746ebaef31d698c702903e7c40980289 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 54a4542a40f111a5b4ae7bc2168e9482037309ed..bec0a8726c6baac4add6dfb11a9436f6fe5afa90 100644 (file)
@@ -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) {
index 706efd0c41902efcb071f0777c0c52c623fef09d..9882ebd8751c833704de75bb5d3ffdefde230453 100644 (file)
@@ -910,7 +910,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 e92fd14c06c711dc3bf6ace69f95f5dd986bac10..8998d6a2728812e280b800ef58b9f0706c670a66 100644 (file)
@@ -13809,18 +13809,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)
@@ -13906,7 +13909,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
                                       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;
index 94f9a1332dbf6e636d268964787a6195a879fa5d..4c6b387fa9dc8e7e3b83e74548804ec6bc262b6a 100644 (file)
@@ -1171,13 +1171,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;
index 0847cc0d96a4b98c0885c0cd3b0873bc3fd9f872..debde2dae7bf920ed6c24a79e65bee58a727312b 100644 (file)
@@ -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);
index 1a59b9ab4aa817701938235dd9ac397d75206098..6f121891430fadad9ed1086e82e61cfa4dc92271 100644 (file)
@@ -175,7 +175,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 a32d3b6e2e12e482f16d4f23eedea11cb8f5da18..17e96fa4786854e2001a9c8553c0500127db403b 100644 (file)
@@ -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);
index a20e3d644523572193893a2f26d19c19d2308590..7a1ad3af08e330c08519f287b600fa425a9b1780 100644 (file)
@@ -401,7 +401,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 fe3a4de1a4331ff86f0b4f0cc85a48b208bca3b5..61dfea791f3f90ef7a1de1ebf3a5d852cb4a0855 100644 (file)
@@ -1139,12 +1139,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;
 
index a34f41ce3599338b9df7739977b7f917e52a9d52..93c38eb6d1879e24cff07435a822ca29a8b6fa40 100644 (file)
@@ -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,
                        &mxsfb->connector);
        if (ret < 0) {
                dev_err(drm->dev, "Cannot setup simple display pipe\n");
index 7abfb561b00cc06665c6618aff1da7938acead79..bd1199b67eb4d19cd88b6053aa2b9a970cfbeacf 100644 (file)
@@ -1083,8 +1083,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;
 
index 2160f64548e03bc028c6f7d9dd36d1aee5ae5745..b92a8f1d01550a70099d822dad285d07a3c5b0e6 100644 (file)
@@ -291,7 +291,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
        ret = drm_universal_plane_init(dev, plane, possible_crtcs,
                                       &omap_plane_funcs, formats,
-                                      nformats, type, NULL);
+                                      nformats, NULL, type, NULL);
        if (ret < 0)
                goto error;
 
index c6ca4f1bbd495bdcf34398d7cdae613ac58d4d81..f0139fa58d5593b770b7bcc4a886530e6d40d569 100644 (file)
@@ -457,7 +457,7 @@ int pl111_display_init(struct drm_device *drm)
        ret = drm_simple_display_pipe_init(drm, &priv->pipe,
                                           &pl111_display_funcs,
                                           formats, ARRAY_SIZE(formats),
-                                          &priv->connector.connector);
+                                          NULL, &priv->connector.connector);
        if (ret)
                return ret;
 
index 5eeae89c138d9037be4214cf841177a04db59442..14c5613b4388a839461915fc448d4772422861a3 100644 (file)
@@ -784,7 +784,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;
 
index dcde6288da6c9dabf4a340c9802c842b2e5f2d28..2b02eccbfb709f97f1a3b59c7ae10a445cc07d7e 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 f870445ebc8df025b0ff9b37696d95552b9e1353..7362d80d236b8af4892ad240a21984908af1a8ba 100644 (file)
@@ -439,8 +439,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 ee4a12da78ab4edad618f270c3b27acfb0fa41e8..ab18659e2a6fc4285208a79694ff92813406cbe2 100644 (file)
@@ -1288,7 +1288,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);
@@ -1327,7 +1327,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 5b3a41f74f21b2da5d130ffba0d8d947d9b44de8..f31cbe898eb33884510566936c09503694aa7ec8 100644 (file)
@@ -392,7 +392,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 5ee0503945c8bfb3a7224aa509e4fba4af2a2751..dceedbe702d77eb0884f821161f96cf9c8b30cf4 100644 (file)
@@ -931,7 +931,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 53a46dda8bd5ed3722d512b820b2760fe8c9faa7..f112308531162c476b3cf7d384ba0bd13dadfe0e 100644 (file)
@@ -1298,7 +1298,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 04cc66d6b96f1e4d49d6dc229b8f7404b0801b02..ae9eb0fff06bc5a7603806456c5c9d90a8b70557 100644 (file)
@@ -735,7 +735,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
 
        ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
                                       &ltdc_plane_funcs, formats, nb_fmt,
-                                      type, NULL);
+                                      NULL, type, NULL);
        if (ret < 0)
                return 0;
 
index ead4f9d4c1eeddf580bde0beadcd0c7e7a480dc7..d45f3a1a0a29d6ddfcd9f497c0e50e9484236d24 100644 (file)
@@ -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);
index e627eeece65890176468dccfe0b390d7469cf878..23810ff7268412a87edb449a6ac6e559ce5f0cb3 100644 (file)
@@ -90,7 +90,7 @@ static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
        ret = drm_universal_plane_init(drm, &layer->plane, 0,
                                       &sun8i_mixer_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 0cb9b90e2e68dd4dd7a1aecbafe2f88c0ab404fd..4df39112e38ec6052beb2165e0550594922174f6 100644 (file)
@@ -678,8 +678,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);
@@ -844,8 +844,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);
@@ -906,8 +906,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 ec43fb7ad9e46889b129eb14fd3b1c0c9489317d..26823a4a07d89eaf7a08e5db889311b63a119fa4 100644 (file)
@@ -225,7 +225,7 @@ tinydrm_display_pipe_init(struct tinydrm_device *tdev,
                return PTR_ERR(connector);
 
        ret = drm_simple_display_pipe_init(drm, &tdev->pipe, funcs, formats,
-                                          format_count, connector);
+                                          format_count, NULL, connector);
        if (ret)
                return ret;
 
index 8853e9a4f00549ef116fffd618691d178cc16a0f..2968b3ebb895714cb8c8faeaf40dff1c996f2259 100644 (file)
@@ -902,7 +902,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);
 
index adcdbd0abef692d46bf574dcf1c5c130b3510e4d..71ba455af915b78298662ee5daf588bd554984b0 100644 (file)
@@ -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;
 
index 6391069498d6da30409c1269ea77c89eb5767589..b8a09807c5de8ebd447af97a56465323672d33d2 100644 (file)
@@ -428,7 +428,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;
@@ -443,7 +443,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);
index 854403509216808a32a96d93eb381765e39a7abc..d1552d3e0652b61a3859ef65a59a12ec501ea1e9 100644 (file)
@@ -624,7 +624,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;
@@ -639,7 +639,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);
index ed9404a7f457c671df4df287475566e029699df7..c4de4ad0543b729fc180adf660f0ddbc7490e4d0 100644 (file)
@@ -1475,7 +1475,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;
@@ -1490,7 +1490,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);
index 4a6252720c10a16cbf686ff52fd5ca112d55063a..18e7634932649783695a0aba16d7fd494648b053 100644 (file)
@@ -540,7 +540,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;
index 9ab3e70448127902aad5414f7fe1e109ed298e21..9d2cc3b11ae71df50d6dc772ee38044fd446b3bf 100644 (file)
@@ -392,6 +392,22 @@ 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).
+        *
+        * 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);
 };
 
 /**
@@ -487,6 +503,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 +546,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,
index 2d36538e4a17ebdabe7fa9e20de25fb8cf952dbe..6d9adbb46293310cb09780ec509f048b94642a41 100644 (file)
@@ -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 */
index 7586c46f68bf22f48a1536c0f27eed0d8d06eb92..76c9101a7fc60993ee7187c1a62a6f7c9248cf0d 100644 (file)
@@ -185,6 +185,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
 /* 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" {
  * 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
  *