Message ID | 12499869afccd632b222eec328a6352111472986.1594230107.git-series.maxime@cerno.tech (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/vc4: Support BCM2711 Display Pipeline | expand |
Hi Maxime On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote: > > In order to avoid a pixel getting stuck in an unflushable FIFO, we need to > recenter the FIFO every time we're doing a modeset and not only if we're > connected to an HDMI monitor. > > Signed-off-by: Maxime Ripard <maxime@cerno.tech> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> > --- > drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++---------------- > 1 file changed, 26 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c > index 4058985940e6..00592c1ada73 100644 > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c > @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, > (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); > } > > +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) > +{ > + u32 drift; > + int ret; > + > + drift = HDMI_READ(HDMI_FIFO_CTL); > + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; > + > + HDMI_WRITE(HDMI_FIFO_CTL, > + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); > + HDMI_WRITE(HDMI_FIFO_CTL, > + drift | VC4_HDMI_FIFO_CTL_RECENTER); > + usleep_range(1000, 1100); > + HDMI_WRITE(HDMI_FIFO_CTL, > + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); > + HDMI_WRITE(HDMI_FIFO_CTL, > + drift | VC4_HDMI_FIFO_CTL_RECENTER); > + > + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & > + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); > + WARN_ONCE(ret, "Timeout waiting for " > + "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); > +} > + > static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) > { > struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; > @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) > } > > if (vc4_encoder->hdmi_monitor) { > - u32 drift; > - > WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & > VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); > HDMI_WRITE(HDMI_SCHEDULER_CONTROL, > @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) > VC4_HDMI_RAM_PACKET_ENABLE); > > vc4_hdmi_set_infoframes(encoder); > - > - drift = HDMI_READ(HDMI_FIFO_CTL); > - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; > - > - HDMI_WRITE(HDMI_FIFO_CTL, > - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); > - HDMI_WRITE(HDMI_FIFO_CTL, > - drift | VC4_HDMI_FIFO_CTL_RECENTER); > - usleep_range(1000, 1100); > - HDMI_WRITE(HDMI_FIFO_CTL, > - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); > - HDMI_WRITE(HDMI_FIFO_CTL, > - drift | VC4_HDMI_FIFO_CTL_RECENTER); > - > - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & > - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); > - WARN_ONCE(ret, "Timeout waiting for " > - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); > } > + > + vc4_hdmi_recenter_fifo(vc4_hdmi); > } > > static enum drm_mode_status > -- > git-series 0.9.1
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4058985940e6..00592c1ada73 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); } +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) +{ + u32 drift; + int ret; + + drift = HDMI_READ(HDMI_FIFO_CTL); + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; + + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + usleep_range(1000, 1100); + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); + WARN_ONCE(ret, "Timeout waiting for " + "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); +} + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } if (vc4_encoder->hdmi_monitor) { - u32 drift; - WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) VC4_HDMI_RAM_PACKET_ENABLE); vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - usleep_range(1000, 1100); - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } + + vc4_hdmi_recenter_fifo(vc4_hdmi); } static enum drm_mode_status
In order to avoid a pixel getting stuck in an unflushable FIFO, we need to recenter the FIFO every time we're doing a modeset and not only if we're connected to an HDMI monitor. Signed-off-by: Maxime Ripard <maxime@cerno.tech> --- drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 20 deletions(-)