Cursor SSPP must be assigned to the last mixer stage, so we assign an immutable zpos property with a value higher than primary/overlay planes, to ensure it will always be on top. Signed-off-by: Arnaud Vrac <avrac@xxxxxxxxxx> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 19 ++++++++++++++----- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 26 +++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 0e7a68714e9e1..6cce0f6cfcb01 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -738,13 +738,22 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) for (i = 0; i < catalog->sspp_count; i++) { enum drm_plane_type type; - if ((catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)) - && cursor_planes_idx < max_crtc_count) - type = DRM_PLANE_TYPE_CURSOR; - else if (primary_planes_idx < max_crtc_count) + if (catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)) { + if (cursor_planes_idx < max_crtc_count) { + type = DRM_PLANE_TYPE_CURSOR; + } else if (catalog->sspp[i].type == SSPP_TYPE_CURSOR) { + /* Cursor SSPP can only be used in the last + * mixer stage, so it doesn't make sense to + * assign two of those to the same CRTC */ + continue; + } else { + type = DRM_PLANE_TYPE_OVERLAY; + } + } else if (primary_planes_idx < max_crtc_count) { type = DRM_PLANE_TYPE_PRIMARY; - else + } else { type = DRM_PLANE_TYPE_OVERLAY; + } DPU_DEBUG("Create plane type %d with features %lx (cur %lx)\n", type, catalog->sspp[i].features, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 128ecdc145260..5a7bb8543866c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -881,7 +881,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; r_pipe->sspp = NULL; - pstate->stage = DPU_STAGE_BASE + pstate->base.normalized_zpos; + if (pipe_hw_caps->type == SSPP_TYPE_CURSOR) { + /* enforce cursor sspp to use the last mixer stage */ + pstate->stage = DPU_STAGE_BASE + + pdpu->catalog->caps->max_mixer_blendstages; + } else { + pstate->stage = DPU_STAGE_BASE + pstate->base.normalized_zpos; + } + if (pstate->stage > DPU_STAGE_BASE + pdpu->catalog->caps->max_mixer_blendstages) { DPU_ERROR("> %d plane mixer stages assigned\n", pdpu->catalog->caps->max_mixer_blendstages); @@ -1463,6 +1470,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *kms = to_dpu_kms(priv->kms); struct dpu_hw_sspp *pipe_hw; + const uint64_t *format_modifiers; uint32_t num_formats; uint32_t supported_rotations; int ret = -EINVAL; @@ -1489,15 +1497,27 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, format_list = pipe_hw->cap->sblk->format_list; num_formats = pipe_hw->cap->sblk->num_formats; + if (pipe_hw->cap->type == SSPP_TYPE_CURSOR) + format_modifiers = NULL; + else + format_modifiers = supported_format_modifiers; + ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, format_list, num_formats, - supported_format_modifiers, type, NULL); + format_modifiers, type, NULL); if (ret) goto clean_plane; pdpu->catalog = kms->catalog; - ret = drm_plane_create_zpos_property(plane, 0, 0, DPU_ZPOS_MAX); + if (pipe_hw->cap->type == SSPP_TYPE_CURSOR) { + /* cursor SSPP can only be used in the last mixer stage, + * enforce it by maxing out the cursor plane zpos */ + ret = drm_plane_create_zpos_immutable_property(plane, DPU_ZPOS_MAX); + } else { + ret = drm_plane_create_zpos_property(plane, 0, 0, DPU_ZPOS_MAX - 1); + } + if (ret) DPU_ERROR("failed to install zpos property, rc = %d\n", ret); -- 2.40.0