From f3444b063890721e7936b7e6a45f664695ee2109 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 7 Dec 2022 12:53:16 +0100 Subject: [PATCH] drm/vc4: hvs: Support zpos on all planes Adds the zpos property to all planes, and creates the dlist by placing the fragments in the correct order based on zpos. Signed-off-by: Dave Stevenson Link: https://lore.kernel.org/r/20221207-rpi-hvs-crtc-misc-v1-5-1f8e0770798b@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hvs.c | 43 +++++++++++++++++++++------------ drivers/gpu/drm/vc4/vc4_kms.c | 1 + drivers/gpu/drm/vc4/vc4_plane.c | 22 ++++++++++++++--- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 56a0a1d8aee0..260efd44a821 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -570,6 +570,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, bool enable_bg_fill = false; u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start; u32 __iomem *dlist_next = dlist_start; + unsigned int zpos = 0; + bool found = false; int idx; if (!drm_dev_enter(dev, &idx)) { @@ -583,23 +585,34 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, } /* Copy all the active planes' dlist contents to the hardware dlist. */ - drm_atomic_crtc_for_each_plane(plane, crtc) { - /* Is this the first active plane? */ - if (dlist_next == dlist_start) { - /* We need to enable background fill when a plane - * could be alpha blending from the background, i.e. - * where no other plane is underneath. It suffices to - * consider the first active plane here since we set - * needs_bg_fill such that either the first plane - * already needs it or all planes on top blend from - * the first or a lower plane. - */ - vc4_plane_state = to_vc4_plane_state(plane->state); - enable_bg_fill = vc4_plane_state->needs_bg_fill; + do { + found = false; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + if (plane->state->normalized_zpos != zpos) + continue; + + /* Is this the first active plane? */ + if (dlist_next == dlist_start) { + /* We need to enable background fill when a plane + * could be alpha blending from the background, i.e. + * where no other plane is underneath. It suffices to + * consider the first active plane here since we set + * needs_bg_fill such that either the first plane + * already needs it or all planes on top blend from + * the first or a lower plane. + */ + vc4_plane_state = to_vc4_plane_state(plane->state); + enable_bg_fill = vc4_plane_state->needs_bg_fill; + } + + dlist_next += vc4_plane_write_dlist(plane, dlist_next); + + found = true; } - dlist_next += vc4_plane_write_dlist(plane, dlist_next); - } + zpos++; + } while (found); writel(SCALER_CTL0_END, dlist_next); dlist_next++; diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 53d9f30460cf..a7e3d47c50f4 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -1074,6 +1074,7 @@ int vc4_kms_load(struct drm_device *dev) dev->mode_config.helper_private = &vc4_mode_config_helpers; dev->mode_config.preferred_depth = 24; dev->mode_config.async_page_flip = true; + dev->mode_config.normalize_zpos = true; ret = vc4_ctm_obj_init(vc4); if (ret) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index bd5acc4a8687..4c2d62361ef5 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1570,9 +1570,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE); + if (type == DRM_PLANE_TYPE_PRIMARY) + drm_plane_create_zpos_immutable_property(plane, 0); + return plane; } +#define VC4_NUM_OVERLAY_PLANES 16 + int vc4_plane_create_additional_planes(struct drm_device *drm) { struct drm_plane *cursor_plane; @@ -1588,24 +1593,35 @@ int vc4_plane_create_additional_planes(struct drm_device *drm) * modest number of planes to expose, that should hopefully * still cover any sane usecase. */ - for (i = 0; i < 16; i++) { + for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) { struct drm_plane *plane = vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, GENMASK(drm->mode_config.num_crtc - 1, 0)); if (IS_ERR(plane)) continue; + + /* Create zpos property. Max of all the overlays + 1 primary + + * 1 cursor plane on a crtc. + */ + drm_plane_create_zpos_property(plane, i + 1, 1, + VC4_NUM_OVERLAY_PLANES + 1); } drm_for_each_crtc(crtc, drm) { /* Set up the legacy cursor after overlay initialization, - * since we overlay planes on the CRTC in the order they were - * initialized. + * since the zpos fallback is that planes are rendered by plane + * ID order, and that then puts the cursor on top. */ cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR, drm_crtc_mask(crtc)); if (!IS_ERR(cursor_plane)) { crtc->cursor = cursor_plane; + + drm_plane_create_zpos_property(cursor_plane, + VC4_NUM_OVERLAY_PLANES + 1, + 1, + VC4_NUM_OVERLAY_PLANES + 1); } }