It is possible to slightly bend the limitations of the HW blender. If two rectangles are contiguous (like two rectangles of a single plane) they can be blended using a single LM blending stage, allowing one to blend more planes via a single LM. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 ++++-- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 37 ++++++++++++++++++----- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 794c5643584f..fbbd7f635d04 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -445,6 +445,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, uint32_t lm_idx; bool bg_alpha_enable = false; + unsigned int stage_indices[DPU_STAGE_MAX] = {}; DECLARE_BITMAP(fetch_active, SSPP_MAX); memset(fetch_active, 0, sizeof(fetch_active)); @@ -469,7 +470,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, mixer, cstate->num_mixers, pstate->stage, format, fb ? fb->modifier : 0, - &pstate->pipe, 0, stage_cfg); + &pstate->pipe, + stage_indices[pstate->stage]++, + stage_cfg); if (pstate->r_pipe.sspp) { set_bit(pstate->r_pipe.sspp->idx, fetch_active); @@ -477,7 +480,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, mixer, cstate->num_mixers, pstate->stage, format, fb ? fb->modifier : 0, - &pstate->r_pipe, 1, stage_cfg); + &pstate->r_pipe, + stage_indices[pstate->stage]++, + stage_cfg); } /* blend config update */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 2e1c544efc4a..43dfe13eb298 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -827,13 +827,6 @@ static int dpu_plane_atomic_check_nopipe(struct drm_plane *plane, if (!new_plane_state->visible) return 0; - pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos; - if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) { - DPU_ERROR("> %d plane stages assigned\n", - pdpu->catalog->caps->max_mixer_blendstages - DPU_STAGE_0); - return -EINVAL; - } - /* state->src is 16.16, src_rect is not */ drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src); @@ -971,6 +964,18 @@ static int dpu_plane_try_multirect(struct dpu_plane_state *pstate, prev_pipe->multirect_index = DPU_SSPP_RECT_0; prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + if (pipe_cfg->dst_rect.y1 == prev_pipe_cfg->dst_rect.y1 && + pipe_cfg->dst_rect.y2 == prev_pipe_cfg->dst_rect.y2 && + pipe_cfg->dst_rect.x1 == prev_pipe_cfg->dst_rect.x2) { + pstate->stage = prev_pstate->stage; + } else if (pipe_cfg->dst_rect.y1 == prev_pipe_cfg->dst_rect.y1 && + pipe_cfg->dst_rect.y2 == prev_pipe_cfg->dst_rect.y2 && + pipe_cfg->dst_rect.x2 == prev_pipe_cfg->dst_rect.x1) { + pstate->stage = prev_pstate->stage; + pipe->multirect_index = DPU_SSPP_RECT_0; + prev_pipe->multirect_index = DPU_SSPP_RECT_1; + } + return true; } @@ -1080,6 +1085,13 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, if (!new_plane_state->visible) return 0; + pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos; + if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) { + DPU_ERROR("> %d plane stages assigned\n", + pdpu->catalog->caps->max_mixer_blendstages - DPU_STAGE_0); + return -EINVAL; + } + pipe->multirect_index = DPU_SSPP_RECT_SOLO; pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; @@ -1221,6 +1233,11 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, max_linewidth = dpu_kms->catalog->caps->max_linewidth; + if (prev_pstate) + pstate->stage = prev_pstate->stage + 1; + else + pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos; + if (drm_rect_width(&r_pipe_cfg->src_rect) == 0) { if (!prev_pstate || !dpu_plane_try_multirect(pstate, prev_pstate, fmt, max_linewidth)) { @@ -1267,6 +1284,12 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, } } + if (pstate->stage >= dpu_kms->catalog->caps->max_mixer_blendstages) { + DPU_ERROR("> %d plane stages assigned\n", + dpu_kms->catalog->caps->max_mixer_blendstages - DPU_STAGE_0); + return -EINVAL; + } + return dpu_plane_atomic_check_pipes(plane, state, crtc_state); } -- 2.39.2