diff mbox series

[18/21] drm/msm/dpu: blend pipes by left and right

Message ID 20240829-sm8650-v6-11-hmd-pocf-mdss-quad-upstream-8-v1-18-bdb05b4b5a2e@linaro.org (mailing list archive)
State Not Applicable
Headers show
Series drm/msm: Support quad pipe with dual-DSI | expand

Commit Message

Jun Nie Aug. 29, 2024, 10:17 a.m. UTC
Blend pipes by left and right. The first 2 pipes are for
left half screen and the later 2 pipes are for right in quad
pipe case.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 13 +++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +++++++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 19 +++++++++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |  4 +++-
 4 files changed, 38 insertions(+), 8 deletions(-)

Comments

Dmitry Baryshkov Aug. 29, 2024, 11:51 a.m. UTC | #1
On Thu, 29 Aug 2024 at 13:21, Jun Nie <jun.nie@linaro.org> wrote:
>
> Blend pipes by left and right. The first 2 pipes are for
> left half screen and the later 2 pipes are for right in quad
> pipe case.
>
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 13 +++++++++++--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +++++++---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 19 +++++++++++++++++--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |  4 +++-
>  4 files changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 3b3cd17976082..8fd56f8f2851f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -574,8 +574,17 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
>                         mixer[i].mixer_op_mode,
>                         ctl->idx - CTL_0);
>
> -               ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> -                       &stage_cfg);
> +               /*
> +                * call dpu_hw_ctl_setup_blendstage() to blend layers per stage cfg.
> +                * There is 4 mixers at most. The first 2 are for the left half, and
> +                * the later 2 are for the right half.
> +                */
> +               if (cstate->num_mixers == 4 && i >= 2)
> +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> +                               &stage_cfg, true);
> +               else
> +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> +                               &stage_cfg, false);
>         }
>  }
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 76793201b984e..5d927f23e35b2 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2049,9 +2049,13 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
>                 if (phys_enc->hw_ctl->ops.update_pending_flush_mixer)
>                         phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx);
>
> -               /* clear all blendstages */
> -               if (phys_enc->hw_ctl->ops.setup_blendstage)
> -                       phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
> +               /* clear all blendstages in both left and right */
> +               if (phys_enc->hw_ctl->ops.setup_blendstage) {
> +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> +                               hw_mixer[i]->idx, NULL, false);
> +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> +                               hw_mixer[i]->idx, NULL, true);
> +               }
>         }
>  }
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> index 602dfad127c2a..2072d18520326 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -478,12 +478,13 @@ static const struct ctl_blend_config ctl_blend_config[][2] = {
>  };
>
>  static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
> -       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
> +       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg, bool right)
>  {
>         struct dpu_hw_blk_reg_map *c = &ctx->hw;
>         u32 mix, ext, mix_ext;
>         u32 mixercfg[5] = { 0 };
>         int i, j;
> +       int pipe_start, pipe_end;
>         int stages;
>         int pipes_per_stage;
>
> @@ -502,13 +503,27 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
>         if (!stage_cfg)
>                 goto exit;
>
> +       /*
> +        * For quad pipe case, blend pipes in right side separately. Otherwise,
> +        * all content is on the left half by defaut (no splitting case).
> +        */
> +       if (!right) {

I think the approach to set PIPES_PER_STAGE to 4 is incorrect. It
complicates the code too much. Instead please use two separate
instances, each one representing a single LM pair and corresponding
set of SW pipes. Yes, you'd have to iterate over them manually.
However I think it's also going to make code simpler.

> +               pipe_start = 0;
> +               pipe_end = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;

pipe_end = pipes_per_stage

> +       } else {
> +               pipe_start = 2;
> +               pipe_end = PIPES_PER_STAGE;

So, the right part always has 2 pipes? What if the
DPU_MIXER_SOURCESPLIT isn't supported?


> +       }
> +
> +       DRM_DEBUG_ATOMIC("blend lm %d on the %s side\n", lm - LM_0,
> +                        right ? "right" : "left");
>         for (i = 0; i <= stages; i++) {
>                 /* overflow to ext register if 'i + 1 > 7' */
>                 mix = (i + 1) & 0x7;
>                 ext = i >= 7;
>                 mix_ext = (i + 1) & 0xf;
>
> -               for (j = 0 ; j < pipes_per_stage; j++) {
> +               for (j = pipe_start; j < pipe_end; j++) {
>                         enum dpu_sspp_multirect_index rect_index =
>                                 stage_cfg->multirect_index[i][j];
>                         enum dpu_sspp pipe = stage_cfg->stage[i][j];
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> index 557ec9a924f81..2dac7885fc5e7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> @@ -25,6 +25,8 @@ struct dpu_hw_ctl;
>  /**
>   * struct dpu_hw_stage_cfg - blending stage cfg
>   * @stage : SSPP_ID at each stage
> + *          The first 2 in PIPES_PER_STAGE(4) are for the first SSPP.
> + *          The 3rd/4th in PIPES_PER_STAGE(4) are for the 2nd SSPP.
>   * @multirect_index: index of the rectangle of SSPP.
>   */
>  struct dpu_hw_stage_cfg {
> @@ -243,7 +245,7 @@ struct dpu_hw_ctl_ops {
>          * @cfg       : blend stage configuration
>          */
>         void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
> -               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
> +               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg, bool right);
>
>         void (*set_active_pipes)(struct dpu_hw_ctl *ctx,
>                 unsigned long *fetch_active);
>
> --
> 2.34.1
>


--
With best wishes
Dmitry
Jun Nie Sept. 3, 2024, 7:53 a.m. UTC | #2
Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 于2024年8月29日周四 19:51写道:
>
> On Thu, 29 Aug 2024 at 13:21, Jun Nie <jun.nie@linaro.org> wrote:
> >
> > Blend pipes by left and right. The first 2 pipes are for
> > left half screen and the later 2 pipes are for right in quad
> > pipe case.
> >
> > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 13 +++++++++++--
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +++++++---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 19 +++++++++++++++++--
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |  4 +++-
> >  4 files changed, 38 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 3b3cd17976082..8fd56f8f2851f 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -574,8 +574,17 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
> >                         mixer[i].mixer_op_mode,
> >                         ctl->idx - CTL_0);
> >
> > -               ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > -                       &stage_cfg);
> > +               /*
> > +                * call dpu_hw_ctl_setup_blendstage() to blend layers per stage cfg.
> > +                * There is 4 mixers at most. The first 2 are for the left half, and
> > +                * the later 2 are for the right half.
> > +                */
> > +               if (cstate->num_mixers == 4 && i >= 2)
> > +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > +                               &stage_cfg, true);
> > +               else
> > +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > +                               &stage_cfg, false);
> >         }
> >  }
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 76793201b984e..5d927f23e35b2 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -2049,9 +2049,13 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> >                 if (phys_enc->hw_ctl->ops.update_pending_flush_mixer)
> >                         phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx);
> >
> > -               /* clear all blendstages */
> > -               if (phys_enc->hw_ctl->ops.setup_blendstage)
> > -                       phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
> > +               /* clear all blendstages in both left and right */
> > +               if (phys_enc->hw_ctl->ops.setup_blendstage) {
> > +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> > +                               hw_mixer[i]->idx, NULL, false);
> > +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> > +                               hw_mixer[i]->idx, NULL, true);
> > +               }
> >         }
> >  }
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > index 602dfad127c2a..2072d18520326 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > @@ -478,12 +478,13 @@ static const struct ctl_blend_config ctl_blend_config[][2] = {
> >  };
> >
> >  static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
> > -       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
> > +       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg, bool right)
> >  {
> >         struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >         u32 mix, ext, mix_ext;
> >         u32 mixercfg[5] = { 0 };
> >         int i, j;
> > +       int pipe_start, pipe_end;
> >         int stages;
> >         int pipes_per_stage;
> >
> > @@ -502,13 +503,27 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
> >         if (!stage_cfg)
> >                 goto exit;
> >
> > +       /*
> > +        * For quad pipe case, blend pipes in right side separately. Otherwise,
> > +        * all content is on the left half by defaut (no splitting case).
> > +        */
> > +       if (!right) {
>
> I think the approach to set PIPES_PER_STAGE to 4 is incorrect. It
> complicates the code too much. Instead please use two separate
> instances, each one representing a single LM pair and corresponding
> set of SW pipes. Yes, you'd have to iterate over them manually.
> However I think it's also going to make code simpler.

OK. I can explore this method.
>
> > +               pipe_start = 0;
> > +               pipe_end = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;
>
> pipe_end = pipes_per_stage
>
> > +       } else {
> > +               pipe_start = 2;
> > +               pipe_end = PIPES_PER_STAGE;
>
> So, the right part always has 2 pipes? What if the
> DPU_MIXER_SOURCESPLIT isn't supported?

Yeah, the case is missed. It should be like this for the right half:
pipe_start = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;
pipe_end = pipes_per_stage == PIPES_PER_STAGE ? PIPES_PER_STAGE : 2;


>
>
> > +       }
> > +
> > +       DRM_DEBUG_ATOMIC("blend lm %d on the %s side\n", lm - LM_0,
> > +                        right ? "right" : "left");
> >         for (i = 0; i <= stages; i++) {
> >                 /* overflow to ext register if 'i + 1 > 7' */
> >                 mix = (i + 1) & 0x7;
> >                 ext = i >= 7;
> >                 mix_ext = (i + 1) & 0xf;
> >
> > -               for (j = 0 ; j < pipes_per_stage; j++) {
> > +               for (j = pipe_start; j < pipe_end; j++) {
> >                         enum dpu_sspp_multirect_index rect_index =
> >                                 stage_cfg->multirect_index[i][j];
> >                         enum dpu_sspp pipe = stage_cfg->stage[i][j];
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > index 557ec9a924f81..2dac7885fc5e7 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > @@ -25,6 +25,8 @@ struct dpu_hw_ctl;
> >  /**
> >   * struct dpu_hw_stage_cfg - blending stage cfg
> >   * @stage : SSPP_ID at each stage
> > + *          The first 2 in PIPES_PER_STAGE(4) are for the first SSPP.
> > + *          The 3rd/4th in PIPES_PER_STAGE(4) are for the 2nd SSPP.
> >   * @multirect_index: index of the rectangle of SSPP.
> >   */
> >  struct dpu_hw_stage_cfg {
> > @@ -243,7 +245,7 @@ struct dpu_hw_ctl_ops {
> >          * @cfg       : blend stage configuration
> >          */
> >         void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
> > -               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
> > +               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg, bool right);
> >
> >         void (*set_active_pipes)(struct dpu_hw_ctl *ctx,
> >                 unsigned long *fetch_active);
> >
> > --
> > 2.34.1
> >
>
>
> --
> With best wishes
> Dmitry
Dmitry Baryshkov Sept. 3, 2024, 9:11 a.m. UTC | #3
On Tue, 3 Sept 2024 at 10:53, Jun Nie <jun.nie@linaro.org> wrote:
>
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 于2024年8月29日周四 19:51写道:
> >
> > On Thu, 29 Aug 2024 at 13:21, Jun Nie <jun.nie@linaro.org> wrote:
> > >
> > > Blend pipes by left and right. The first 2 pipes are for
> > > left half screen and the later 2 pipes are for right in quad
> > > pipe case.
> > >
> > > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > > ---
> > >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 13 +++++++++++--
> > >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +++++++---
> > >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 19 +++++++++++++++++--
> > >  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |  4 +++-
> > >  4 files changed, 38 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > index 3b3cd17976082..8fd56f8f2851f 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > @@ -574,8 +574,17 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
> > >                         mixer[i].mixer_op_mode,
> > >                         ctl->idx - CTL_0);
> > >
> > > -               ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > > -                       &stage_cfg);
> > > +               /*
> > > +                * call dpu_hw_ctl_setup_blendstage() to blend layers per stage cfg.
> > > +                * There is 4 mixers at most. The first 2 are for the left half, and
> > > +                * the later 2 are for the right half.
> > > +                */
> > > +               if (cstate->num_mixers == 4 && i >= 2)
> > > +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > > +                               &stage_cfg, true);
> > > +               else
> > > +                       ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> > > +                               &stage_cfg, false);
> > >         }
> > >  }
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > index 76793201b984e..5d927f23e35b2 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > @@ -2049,9 +2049,13 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> > >                 if (phys_enc->hw_ctl->ops.update_pending_flush_mixer)
> > >                         phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx);
> > >
> > > -               /* clear all blendstages */
> > > -               if (phys_enc->hw_ctl->ops.setup_blendstage)
> > > -                       phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
> > > +               /* clear all blendstages in both left and right */
> > > +               if (phys_enc->hw_ctl->ops.setup_blendstage) {
> > > +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> > > +                               hw_mixer[i]->idx, NULL, false);
> > > +                       phys_enc->hw_ctl->ops.setup_blendstage(ctl,
> > > +                               hw_mixer[i]->idx, NULL, true);
> > > +               }
> > >         }
> > >  }
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > > index 602dfad127c2a..2072d18520326 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> > > @@ -478,12 +478,13 @@ static const struct ctl_blend_config ctl_blend_config[][2] = {
> > >  };
> > >
> > >  static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
> > > -       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
> > > +       enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg, bool right)
> > >  {
> > >         struct dpu_hw_blk_reg_map *c = &ctx->hw;
> > >         u32 mix, ext, mix_ext;
> > >         u32 mixercfg[5] = { 0 };
> > >         int i, j;
> > > +       int pipe_start, pipe_end;
> > >         int stages;
> > >         int pipes_per_stage;
> > >
> > > @@ -502,13 +503,27 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
> > >         if (!stage_cfg)
> > >                 goto exit;
> > >
> > > +       /*
> > > +        * For quad pipe case, blend pipes in right side separately. Otherwise,
> > > +        * all content is on the left half by defaut (no splitting case).
> > > +        */
> > > +       if (!right) {
> >
> > I think the approach to set PIPES_PER_STAGE to 4 is incorrect. It
> > complicates the code too much. Instead please use two separate
> > instances, each one representing a single LM pair and corresponding
> > set of SW pipes. Yes, you'd have to iterate over them manually.
> > However I think it's also going to make code simpler.
>
> OK. I can explore this method.
> >
> > > +               pipe_start = 0;
> > > +               pipe_end = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;
> >
> > pipe_end = pipes_per_stage
> >
> > > +       } else {
> > > +               pipe_start = 2;
> > > +               pipe_end = PIPES_PER_STAGE;
> >
> > So, the right part always has 2 pipes? What if the
> > DPU_MIXER_SOURCESPLIT isn't supported?
>
> Yeah, the case is missed. It should be like this for the right half:
> pipe_start = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;
> pipe_end = pipes_per_stage == PIPES_PER_STAGE ? PIPES_PER_STAGE : 2;

Well, we can be better than that and use
pipe_start = left ? 0 : 2
pipe_end = pipe_start + pipes_per_stage;

>
>
> >
> >
> > > +       }
> > > +
> > > +       DRM_DEBUG_ATOMIC("blend lm %d on the %s side\n", lm - LM_0,
> > > +                        right ? "right" : "left");
> > >         for (i = 0; i <= stages; i++) {
> > >                 /* overflow to ext register if 'i + 1 > 7' */
> > >                 mix = (i + 1) & 0x7;
> > >                 ext = i >= 7;
> > >                 mix_ext = (i + 1) & 0xf;
> > >
> > > -               for (j = 0 ; j < pipes_per_stage; j++) {
> > > +               for (j = pipe_start; j < pipe_end; j++) {
> > >                         enum dpu_sspp_multirect_index rect_index =
> > >                                 stage_cfg->multirect_index[i][j];
> > >                         enum dpu_sspp pipe = stage_cfg->stage[i][j];
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > > index 557ec9a924f81..2dac7885fc5e7 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> > > @@ -25,6 +25,8 @@ struct dpu_hw_ctl;
> > >  /**
> > >   * struct dpu_hw_stage_cfg - blending stage cfg
> > >   * @stage : SSPP_ID at each stage
> > > + *          The first 2 in PIPES_PER_STAGE(4) are for the first SSPP.
> > > + *          The 3rd/4th in PIPES_PER_STAGE(4) are for the 2nd SSPP.
> > >   * @multirect_index: index of the rectangle of SSPP.
> > >   */
> > >  struct dpu_hw_stage_cfg {
> > > @@ -243,7 +245,7 @@ struct dpu_hw_ctl_ops {
> > >          * @cfg       : blend stage configuration
> > >          */
> > >         void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
> > > -               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
> > > +               enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg, bool right);
> > >
> > >         void (*set_active_pipes)(struct dpu_hw_ctl *ctx,
> > >                 unsigned long *fetch_active);
> > >
> > > --
> > > 2.34.1
> > >
> >
> >
> > --
> > With best wishes
> > Dmitry
diff mbox series

Patch

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 3b3cd17976082..8fd56f8f2851f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -574,8 +574,17 @@  static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
 			mixer[i].mixer_op_mode,
 			ctl->idx - CTL_0);
 
-		ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
-			&stage_cfg);
+		/*
+		 * call dpu_hw_ctl_setup_blendstage() to blend layers per stage cfg.
+		 * There is 4 mixers at most. The first 2 are for the left half, and
+		 * the later 2 are for the right half.
+		 */
+		if (cstate->num_mixers == 4 && i >= 2)
+			ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
+				&stage_cfg, true);
+		else
+			ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
+				&stage_cfg, false);
 	}
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 76793201b984e..5d927f23e35b2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2049,9 +2049,13 @@  static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
 		if (phys_enc->hw_ctl->ops.update_pending_flush_mixer)
 			phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx);
 
-		/* clear all blendstages */
-		if (phys_enc->hw_ctl->ops.setup_blendstage)
-			phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
+		/* clear all blendstages in both left and right */
+		if (phys_enc->hw_ctl->ops.setup_blendstage) {
+			phys_enc->hw_ctl->ops.setup_blendstage(ctl,
+				hw_mixer[i]->idx, NULL, false);
+			phys_enc->hw_ctl->ops.setup_blendstage(ctl,
+				hw_mixer[i]->idx, NULL, true);
+		}
 	}
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 602dfad127c2a..2072d18520326 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -478,12 +478,13 @@  static const struct ctl_blend_config ctl_blend_config[][2] = {
 };
 
 static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
-	enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
+	enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg, bool right)
 {
 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
 	u32 mix, ext, mix_ext;
 	u32 mixercfg[5] = { 0 };
 	int i, j;
+	int pipe_start, pipe_end;
 	int stages;
 	int pipes_per_stage;
 
@@ -502,13 +503,27 @@  static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
 	if (!stage_cfg)
 		goto exit;
 
+	/*
+	 * For quad pipe case, blend pipes in right side separately. Otherwise,
+	 * all content is on the left half by defaut (no splitting case).
+	 */
+	if (!right) {
+		pipe_start = 0;
+		pipe_end = pipes_per_stage == PIPES_PER_STAGE ? 2 : 1;
+	} else {
+		pipe_start = 2;
+		pipe_end = PIPES_PER_STAGE;
+	}
+
+	DRM_DEBUG_ATOMIC("blend lm %d on the %s side\n", lm - LM_0,
+			 right ? "right" : "left");
 	for (i = 0; i <= stages; i++) {
 		/* overflow to ext register if 'i + 1 > 7' */
 		mix = (i + 1) & 0x7;
 		ext = i >= 7;
 		mix_ext = (i + 1) & 0xf;
 
-		for (j = 0 ; j < pipes_per_stage; j++) {
+		for (j = pipe_start; j < pipe_end; j++) {
 			enum dpu_sspp_multirect_index rect_index =
 				stage_cfg->multirect_index[i][j];
 			enum dpu_sspp pipe = stage_cfg->stage[i][j];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 557ec9a924f81..2dac7885fc5e7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -25,6 +25,8 @@  struct dpu_hw_ctl;
 /**
  * struct dpu_hw_stage_cfg - blending stage cfg
  * @stage : SSPP_ID at each stage
+ *          The first 2 in PIPES_PER_STAGE(4) are for the first SSPP.
+ *          The 3rd/4th in PIPES_PER_STAGE(4) are for the 2nd SSPP.
  * @multirect_index: index of the rectangle of SSPP.
  */
 struct dpu_hw_stage_cfg {
@@ -243,7 +245,7 @@  struct dpu_hw_ctl_ops {
 	 * @cfg       : blend stage configuration
 	 */
 	void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
-		enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
+		enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg, bool right);
 
 	void (*set_active_pipes)(struct dpu_hw_ctl *ctx,
 		unsigned long *fetch_active);