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 df4c2e503fa5..4b5b2b7ed494 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -456,6 +456,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)); @@ -480,7 +481,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); @@ -488,7 +491,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 61afd1cf033d..e7a157feab22 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -809,13 +809,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; - } - fb_rect.x2 = new_plane_state->fb->width; fb_rect.y2 = new_plane_state->fb->height; @@ -952,6 +945,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; } @@ -1054,6 +1059,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; @@ -1189,6 +1201,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)) { @@ -1235,6 +1252,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); } -- 2.39.2