Hi Maxime,

Thanks for V2 patch.


On 10/28/20 9:41 PM, Maxime Ripard wrote:
> The current HVS muxing code will consider the CRTCs in a given state to
> setup their muxing in the HVS, and disable the other CRTCs muxes.
>
> However, it's valid to only update a single CRTC with a state, and in this
> situation we would mux out a CRTC that was enabled but left untouched by
> the new state.
>
> Fix this by setting a flag on the CRTC state when the muxing has been
> changed, and only change the muxing configuration when that flag is there.
>
> Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically")
> Signed-off-by: Maxime Ripard <max...@cerno.tech>
> ---
>   drivers/gpu/drm/vc4/vc4_drv.h |  1 +-
>   drivers/gpu/drm/vc4/vc4_kms.c | 84 +++++++++++++++++++++---------------
>   2 files changed, 50 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index c6208b040f77..c074c0538e57 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -523,6 +523,7 @@ struct vc4_crtc_state {
>       struct drm_mm_node mm;
>       bool feed_txp;
>       bool txp_armed;
> +     bool needs_muxing;
>       unsigned int assigned_channel;
>   
>       struct {
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 2aa726b7422c..409aeb19d210 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -224,10 +224,7 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
>   {
>       struct drm_crtc_state *crtc_state;
>       struct drm_crtc *crtc;
> -     unsigned char dsp2_mux = 0;
> -     unsigned char dsp3_mux = 3;
> -     unsigned char dsp4_mux = 3;
> -     unsigned char dsp5_mux = 3;
> +     unsigned char mux;
>       unsigned int i;
>       u32 reg;
>   
> @@ -235,50 +232,59 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev 
> *vc4,
>               struct vc4_crtc_state *vc4_state = 
> to_vc4_crtc_state(crtc_state);
>               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>   
> -             if (!crtc_state->active)
> +             if (!vc4_state->needs_muxing)
>                       continue;
>   
>               switch (vc4_crtc->data->hvs_output) {
>               case 2:
> -                     dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
> +                     mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
> +                     reg = HVS_READ(SCALER_DISPECTRL);
> +                     HVS_WRITE(SCALER_DISPECTRL,
> +                               (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
> +                               VC4_SET_FIELD(mux, 
> SCALER_DISPECTRL_DSP2_MUX));
>                       break;
>   
>               case 3:
> -                     dsp3_mux = vc4_state->assigned_channel;
> +                     if (vc4_state->assigned_channel == 
> VC4_HVS_CHANNEL_DISABLED)
> +                             mux = 3;
> +                     else
> +                             mux = vc4_state->assigned_channel;
> +
> +                     reg = HVS_READ(SCALER_DISPCTRL);
> +                     HVS_WRITE(SCALER_DISPCTRL,
> +                               (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
> +                               VC4_SET_FIELD(mux, SCALER_DISPCTRL_DSP3_MUX));
>                       break;
>   
>               case 4:
> -                     dsp4_mux = vc4_state->assigned_channel;
> +                     if (vc4_state->assigned_channel == 
> VC4_HVS_CHANNEL_DISABLED)
> +                             mux = 3;
> +                     else
> +                             mux = vc4_state->assigned_channel;
> +
> +                     reg = HVS_READ(SCALER_DISPEOLN);
> +                     HVS_WRITE(SCALER_DISPEOLN,
> +                               (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
> +                               VC4_SET_FIELD(mux, SCALER_DISPEOLN_DSP4_MUX));
> +
>                       break;
>   
>               case 5:
> -                     dsp5_mux = vc4_state->assigned_channel;
> +                     if (vc4_state->assigned_channel == 
> VC4_HVS_CHANNEL_DISABLED)
> +                             mux = 3;
> +                     else
> +                             mux = vc4_state->assigned_channel;
> +
> +                     reg = HVS_READ(SCALER_DISPDITHER);
> +                     HVS_WRITE(SCALER_DISPDITHER,
> +                               (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
> +                               VC4_SET_FIELD(mux, 
> SCALER_DISPDITHER_DSP5_MUX));
>                       break;
>   
>               default:
>                       break;
>               }
>       }
> -
> -     reg = HVS_READ(SCALER_DISPECTRL);
> -     HVS_WRITE(SCALER_DISPECTRL,
> -               (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
> -               VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
> -
> -     reg = HVS_READ(SCALER_DISPCTRL);
> -     HVS_WRITE(SCALER_DISPCTRL,
> -               (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
> -               VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
> -
> -     reg = HVS_READ(SCALER_DISPEOLN);
> -     HVS_WRITE(SCALER_DISPEOLN,
> -               (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
> -               VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
> -
> -     reg = HVS_READ(SCALER_DISPDITHER);
> -     HVS_WRITE(SCALER_DISPDITHER,
> -               (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
> -               VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
>   }
>   
>   static void
> @@ -769,21 +775,29 @@ static int vc4_pv_muxing_atomic_check(struct drm_device 
> *dev,
>               return -EINVAL;
>   
>       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
> new_crtc_state, i) {
> +             struct vc4_crtc_state *old_vc4_crtc_state =
> +                     to_vc4_crtc_state(old_crtc_state);

In my opinion, the old_vc4_crtc_state definition is better to move to 
patch6.
Build error occurs in patch6 because old_vc4_crtc_state is used in patch6.


Best regards,
Hoegeun

>               struct vc4_crtc_state *new_vc4_crtc_state =
>                       to_vc4_crtc_state(new_crtc_state);
>               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>               unsigned int matching_channels;
>   
> -             if (old_crtc_state->enable && !new_crtc_state->enable) {
> -                     hvs_state->unassigned_channels |= 
> BIT(old_vc4_crtc_state->assigned_channel);
> -                     new_vc4_crtc_state->assigned_channel = 
> VC4_HVS_CHANNEL_DISABLED;
> +             /* Nothing to do here, let's skip it */
> +             if ((old_crtc_state->enable && new_crtc_state->enable) ||
> +                 (!old_crtc_state->enable && !new_crtc_state->enable)) {
> +                     new_vc4_crtc_state->needs_muxing = false;
> +                     continue;
>               }
>   
> -             if (!new_crtc_state->enable)
> -                     continue;
> +             /* Muxing will need to be modified, mark it as such */
> +             new_vc4_crtc_state->needs_muxing = true;
>   
> -             if (new_vc4_crtc_state->assigned_channel != 
> VC4_HVS_CHANNEL_DISABLED)
> +             /* If we're disabling our CRTC, we put back our channel */
> +             if (old_crtc_state->enable && !new_crtc_state->enable) {
> +                     hvs_state->unassigned_channels |= 
> BIT(old_vc4_crtc_state->assigned_channel);
> +                     new_vc4_crtc_state->assigned_channel = 
> VC4_HVS_CHANNEL_DISABLED;
>                       continue;
> +             }
>   
>               /*
>                * The problem we have to solve here is that we have
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to