[Freedreno] [PATCH v7 27/32] drm/msm/dpu: add support for wide planes

Dmitry Baryshkov dmitry.baryshkov at linaro.org
Thu Mar 30 03:30:48 UTC 2023


On 30/03/2023 05:53, Abhinav Kumar wrote:
> 
> 
> On 3/16/2023 9:16 AM, Dmitry Baryshkov wrote:
>> It is possible to use multirect feature and split source to use the SSPP
>> to output two consecutive rectangles. This commit brings in this
>> capability to support wider screen resolutions.
>>
>> Tested-by: Abhinav Kumar <quic_abhinavk at quicinc.com> # sc7280
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  19 ++-
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 136 +++++++++++++++++++---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |   4 +
>>   3 files changed, 142 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 217a8112f1a2..90b406e409d3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -481,6 +481,15 @@ static void _dpu_crtc_blend_setup_mixer(struct 
>> drm_crtc *crtc,
>>                          format, fb ? fb->modifier : 0,
>>                          &pstate->pipe, 0, stage_cfg);
>> +        if (pstate->r_pipe.sspp) {
>> +            set_bit(pstate->r_pipe.sspp->idx, fetch_active);
>> +            _dpu_crtc_blend_setup_pipe(crtc, plane,
>> +                           mixer, cstate->num_mixers,
>> +                           pstate->stage,
>> +                           format, fb ? fb->modifier : 0,
>> +                           &pstate->r_pipe, 1, stage_cfg);
>> +        }
>> +
>>           /* blend config update */
>>           for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
>>               _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format);
>> @@ -1341,10 +1350,16 @@ static int _dpu_debugfs_status_show(struct 
>> seq_file *s, void *data)
>>           seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
>>               state->crtc_x, state->crtc_y, state->crtc_w,
>>               state->crtc_h);
>> -        seq_printf(s, "\tsspp:%s\n",
>> +        seq_printf(s, "\tsspp[0]:%s\n",
>>                  pstate->pipe.sspp->cap->name);
>> -        seq_printf(s, "\tmultirect: mode: %d index: %d\n",
>> +        seq_printf(s, "\tmultirect[0]: mode: %d index: %d\n",
>>               pstate->pipe.multirect_mode, pstate->pipe.multirect_index);
>> +        if (pstate->r_pipe.sspp) {
>> +            seq_printf(s, "\tsspp[1]:%s\n",
>> +                   pstate->r_pipe.sspp->cap->name);
>> +            seq_printf(s, "\tmultirect[1]: mode: %d index: %d\n",
>> +                   pstate->r_pipe.multirect_mode, 
>> pstate->r_pipe.multirect_index);
>> +        }
>>           seq_puts(s, "\n");
>>       }
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> index f52120b05b6e..73db15d76059 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> @@ -701,6 +701,10 @@ static void _dpu_plane_color_fill(struct 
>> dpu_plane *pdpu,
>>       /* update sspp */
>>       _dpu_plane_color_fill_pipe(pstate, &pstate->pipe, 
>> &pstate->pipe_cfg.dst_rect,
>>                      fill_color, fmt);
>> +
>> +    if (pstate->r_pipe.sspp)
>> +        _dpu_plane_color_fill_pipe(pstate, &pstate->r_pipe, 
>> &pstate->r_pipe_cfg.dst_rect,
>> +                       fill_color, fmt);
>>   }
>>   int dpu_plane_validate_multirect_v2(struct 
>> dpu_multirect_plane_states *plane)
>> @@ -959,9 +963,12 @@ static int dpu_plane_atomic_check(struct 
>> drm_plane *plane,
>>       int ret = 0, min_scale;
>>       struct dpu_plane *pdpu = to_dpu_plane(plane);
>>       struct dpu_plane_state *pstate = 
>> to_dpu_plane_state(new_plane_state);
>> +    struct dpu_sw_pipe *pipe = &pstate->pipe;
>> +    struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
>>       const struct drm_crtc_state *crtc_state = NULL;
>>       const struct dpu_format *fmt;
>>       struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
>> +    struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
>>       struct drm_rect fb_rect = { 0 };
>>       uint32_t max_linewidth;
>>       unsigned int rotation;
>> @@ -985,8 +992,11 @@ static int dpu_plane_atomic_check(struct 
>> drm_plane *plane,
>>       if (!new_plane_state->visible)
>>           return 0;
>> -    pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO;
>> -    pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE;
>> +    pipe->multirect_index = DPU_SSPP_RECT_SOLO;
>> +    pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
>> +    r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
>> +    r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
>> +    r_pipe->sspp = NULL;
>>       pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos;
>>       if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) {
>> @@ -1016,21 +1026,67 @@ static int dpu_plane_atomic_check(struct 
>> drm_plane *plane,
>>           return -E2BIG;
>>       }
>> +    fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb));
>> +
>>       max_linewidth = pdpu->catalog->caps->max_linewidth;
>> -    /* check decimated source width */
>>       if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
>> -        DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
>> -                DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
>> -        return -E2BIG;
>> -    }
>> +        /*
>> +         * In parallel multirect case only the half of the usual width
>> +         * is supported for tiled formats. If we are here, we know that
>> +         * full width is more than max_linewidth, thus each rect is
>> +         * wider than allowed.
>> +         */
>> +        if (DPU_FORMAT_IS_UBWC(fmt)) {
>> +            DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " 
>> line:%u, tiled format\n",
>> +                    DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
>> +            return -E2BIG;
>> +        }
> 
> I am seeing a strange issue due to this check. Looks like Chrome 
> compositor tries to do the first frame with UBWC. When I bootup with my 
> DP monitor connected, it tries to use 2560x1440 with UBWC enabled but 
> then fails and then uses linear format and works.
> 
> I confirmed by commenting out this check that its always UBWC.
> 
> I feel this is a compositor issue. If someone can confirm this that 
> would be great because there is nothing wrong with this check.

Yes, I think it is a compositor issue (or misfeature).

> 
> I only want to report this because when this series is cherry-picked and 
> someone tries to bootup with DP connected and it if it does hit this 
> check based on which monitor they try, UBWC no longer works.
> 
> If we can move on and leave that out as compositor issue, I will add my 
> R-b once the other comment is responded to.
> 
> Rest of the testing looks fine.
> 
>> -    fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb));
>> +        if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
>> +            DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " 
>> line:%u\n",
>> +                    DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
>> +            return -E2BIG;
>> +        }
>> -    ret = dpu_plane_atomic_check_pipe(pdpu, &pstate->pipe, pipe_cfg, 
>> fmt);
>> +        if (drm_rect_width(&pipe_cfg->src_rect) != 
>> drm_rect_width(&pipe_cfg->dst_rect) ||
>> +            drm_rect_height(&pipe_cfg->src_rect) != 
>> drm_rect_height(&pipe_cfg->dst_rect) ||
>> +            (!test_bit(DPU_SSPP_SMART_DMA_V1, 
>> &pipe->sspp->cap->features) &&
>> +             !test_bit(DPU_SSPP_SMART_DMA_V2, 
>> &pipe->sspp->cap->features)) ||
>> +            DPU_FORMAT_IS_YUV(fmt)) {
>> +            DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " 
>> line:%u, can't use split source\n",
>> +                    DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
>> +            return -E2BIG;
>> +        }
>> +
>> +        /*
>> +         * Use multirect for wide plane. We do not support dynamic
>> +         * assignment of SSPPs, so we know the configuration.
>> +         */
>> +        pipe->multirect_index = DPU_SSPP_RECT_0;
>> +        pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
>> +
>> +        r_pipe->sspp = pipe->sspp;
>> +        r_pipe->multirect_index = DPU_SSPP_RECT_1;
>> +        r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
>> +
>> +        *r_pipe_cfg = *pipe_cfg;
>> +        pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + 
>> pipe_cfg->src_rect.x2) >> 1;
>> +        pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + 
>> pipe_cfg->dst_rect.x2) >> 1;
>> +        r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
>> +        r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
>> +    }
>> +
>> +    ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
>>       if (ret)
>>           return ret;
>> +    if (r_pipe->sspp) {
>> +        ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, 
>> fmt);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>>       supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0;
>>       if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION))
>> @@ -1097,8 +1153,10 @@ void dpu_plane_flush(struct drm_plane *plane)
>>       else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG)
>>           /* force 100% alpha */
>>           _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF);
>> -    else
>> +    else {
>>           dpu_plane_flush_csc(pdpu, &pstate->pipe);
>> +        dpu_plane_flush_csc(pdpu, &pstate->r_pipe);
>> +    }
>>       /* flag h/w flush complete */
>>       if (plane->state)
>> @@ -1210,13 +1268,14 @@ static void 
>> dpu_plane_sspp_atomic_update(struct drm_plane *plane)
>>       struct drm_plane_state *state = plane->state;
>>       struct dpu_plane_state *pstate = to_dpu_plane_state(state);
>>       struct dpu_sw_pipe *pipe = &pstate->pipe;
>> +    struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
>>       struct drm_crtc *crtc = state->crtc;
>>       struct drm_framebuffer *fb = state->fb;
>>       bool is_rt_pipe;
>>       const struct dpu_format *fmt =
>>           to_dpu_format(msm_framebuffer_format(fb));
>>       struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
>> -
>> +    struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
>>       struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
>>       struct msm_gem_address_space *aspace = kms->base.aspace;
>>       struct dpu_hw_fmt_layout layout;
>> @@ -1244,6 +1303,12 @@ static void dpu_plane_sspp_atomic_update(struct 
>> drm_plane *plane)
>>                      drm_mode_vrefresh(&crtc->mode),
>>                      layout_valid ? &layout : NULL);
>> +    if (r_pipe->sspp) {
>> +        dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
>> +                       drm_mode_vrefresh(&crtc->mode),
>> +                       layout_valid ? &layout : NULL);
>> +    }
>> +
>>       if (pstate->needs_qos_remap)
>>           pstate->needs_qos_remap = false;
>> @@ -1251,16 +1316,31 @@ static void 
>> dpu_plane_sspp_atomic_update(struct drm_plane *plane)
>>                               &crtc->mode, pipe_cfg);
>>       pstate->plane_clk = _dpu_plane_calc_clk(&crtc->mode, pipe_cfg);
>> +
>> +    if (r_pipe->sspp) {
>> +        pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, 
>> fmt, &crtc->mode, r_pipe_cfg);
>> +
>> +        pstate->plane_clk = max(pstate->plane_clk, 
>> _dpu_plane_calc_clk(&crtc->mode, r_pipe_cfg));
>> +    }
>>   }
>>   static void _dpu_plane_atomic_disable(struct drm_plane *plane)
>>   {
>>       struct drm_plane_state *state = plane->state;
>>       struct dpu_plane_state *pstate = to_dpu_plane_state(state);
>> +    struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
>>       trace_dpu_plane_disable(DRMID(plane), false,
>>                   pstate->pipe.multirect_mode);
>> +    if (r_pipe->sspp) {
>> +        r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
>> +        r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
>> +
>> +        if (r_pipe->sspp->ops.setup_multirect)
>> +            r_pipe->sspp->ops.setup_multirect(r_pipe);
>> +    }
> 
> Dont we need to do this even for pstate->pipe?

No. pstate->pipe will be set up when we call 
dpu_plane_sspp_atomic_update() next time. It doesn't seem to matter if 
the disabled SSPP is setup for REC_SOLO or REC_0. We have to ensure that 
REC_1 is disabled so that it doesn't conflict with REC_SOLO setup.

>> +
>>       pstate->pending = true;
>>   }
>> @@ -1293,6 +1373,9 @@ static void dpu_plane_destroy(struct drm_plane 
>> *plane)
>>           pstate = to_dpu_plane_state(plane->state);
>>           _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false, 
>> DPU_PLANE_QOS_PANIC_CTRL);
>> +        if (pstate->r_pipe.sspp)
>> +            _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false, 
>> DPU_PLANE_QOS_PANIC_CTRL);
>> +
>>           mutex_destroy(&pdpu->lock);
>>           /* this will destroy the states as well */
>> @@ -1373,12 +1456,29 @@ static void 
>> dpu_plane_atomic_print_state(struct drm_printer *p,
>>           const struct drm_plane_state *state)
>>   {
>>       const struct dpu_plane_state *pstate = to_dpu_plane_state(state);
>> +    const struct dpu_sw_pipe *pipe = &pstate->pipe;
>> +    const struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
>> +    const struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
>> +    const struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
>>       drm_printf(p, "\tstage=%d\n", pstate->stage);
>> -    drm_printf(p, "\tsspp=%s\n", pstate->pipe.sspp->cap->name);
>> -    drm_printf(p, "\tmultirect_mode=%s\n", 
>> dpu_get_multirect_mode(pstate->pipe.multirect_mode));
>> -    drm_printf(p, "\tmultirect_index=%s\n",
>> -           dpu_get_multirect_index(pstate->pipe.multirect_index));
>> +
>> +    drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
>> +    drm_printf(p, "\tmultirect_mode[0]=%s\n", 
>> dpu_get_multirect_mode(pipe->multirect_mode));
>> +    drm_printf(p, "\tmultirect_index[0]=%s\n",
>> +           dpu_get_multirect_index(pipe->multirect_index));
>> +    drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->src_rect));
>> +    drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->dst_rect));
>> +
>> +    if (r_pipe->sspp) {
>> +        drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
>> +        drm_printf(p, "\tmultirect_mode[1]=%s\n",
>> +               dpu_get_multirect_mode(r_pipe->multirect_mode));
>> +        drm_printf(p, "\tmultirect_index[1]=%s\n",
>> +               dpu_get_multirect_index(r_pipe->multirect_index));
>> +        drm_printf(p, "\tsrc[1]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&r_pipe_cfg->src_rect));
>> +        drm_printf(p, "\tdst[1]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&r_pipe_cfg->dst_rect));
>> +    }
>>   }
>>   static void dpu_plane_reset(struct drm_plane *plane)
>> @@ -1412,6 +1512,10 @@ static void dpu_plane_reset(struct drm_plane 
>> *plane)
>>        * This is the place where the state is allocated, so fill it 
>> fully.
>>        */
>>       pstate->pipe.sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
>> +    pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO;
>> +    pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE;
>> +
>> +    pstate->r_pipe.sspp = NULL;
>>       __drm_atomic_helper_plane_reset(plane, &pstate->base);
>>   }
>> @@ -1428,6 +1532,8 @@ void dpu_plane_danger_signal_ctrl(struct 
>> drm_plane *plane, bool enable)
>>       pm_runtime_get_sync(&dpu_kms->pdev->dev);
>>       _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable, 
>> DPU_PLANE_QOS_PANIC_CTRL);
>> +    if (pstate->r_pipe.sspp)
>> +        _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable, 
>> DPU_PLANE_QOS_PANIC_CTRL);
>>       pm_runtime_put_sync(&dpu_kms->pdev->dev);
>>   }
>>   #endif
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> index 0ca9002015ff..7490ffd94d03 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> @@ -19,7 +19,9 @@
>>    * @base:    base drm plane state object
>>    * @aspace:    pointer to address space for input/output buffers
>>    * @pipe:    software pipe description
>> + * @r_pipe:    software pipe description of the second pipe
>>    * @pipe_cfg:    software pipe configuration
>> + * @r_pipe_cfg:    software pipe configuration for the second pipe
>>    * @stage:    assigned by crtc blender
>>    * @needs_qos_remap: qos remap settings need to be updated
>>    * @multirect_index: index of the rectangle of SSPP
>> @@ -34,7 +36,9 @@ struct dpu_plane_state {
>>       struct drm_plane_state base;
>>       struct msm_gem_address_space *aspace;
>>       struct dpu_sw_pipe pipe;
>> +    struct dpu_sw_pipe r_pipe;
>>       struct dpu_sw_pipe_cfg pipe_cfg;
>> +    struct dpu_sw_pipe_cfg r_pipe_cfg;
>>       enum dpu_stage stage;
>>       bool needs_qos_remap;
>>       bool pending;

-- 
With best wishes
Dmitry



More information about the Freedreno mailing list