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.barysh...@linaro.org>
---
 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

Reply via email to