Hi Maxime Thanks for the patch. On Fri, 7 May 2021 at 16:06, Maxime Ripard <maxime@xxxxxxxxxx> wrote: > > It looks like some displays (like the LG 27UL850-W) don't enable the > scrambling when the HDMI driver enables it. However, if we set later the > scrambler enable bit, the display will work as expected. > > Let's create delayed work queue to periodically look at the display > scrambling status, and if it's not set yet try to enable it again. > > Signed-off-by: Maxime Ripard <maxime@xxxxxxxxxx> Reviewed-by: Dave Stevenson <dave.stevenson@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++++++++++ > drivers/gpu/drm/vc4/vc4_hdmi.h | 2 ++ > 2 files changed, 27 insertions(+) > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c > index bda12fea0dce..4fa7ea419594 100644 > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c > @@ -482,6 +482,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, > return true; > } > > +#define SCRAMBLING_POLLING_DELAY_MS 1000 > + > static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) > { > struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; > @@ -498,6 +500,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) > > HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) | > VC5_HDMI_SCRAMBLER_CTL_ENABLE); > + > + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, > + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); > } > > static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) > @@ -516,6 +521,9 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) > if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode)) > return; > > + if (delayed_work_pending(&vc4_hdmi->scrambling_work)) > + cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); > + > HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) & > ~VC5_HDMI_SCRAMBLER_CTL_ENABLE); > > @@ -523,6 +531,22 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) > drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); > } > > +static void vc4_hdmi_scrambling_wq(struct work_struct *work) > +{ > + struct vc4_hdmi *vc4_hdmi = container_of(to_delayed_work(work), > + struct vc4_hdmi, > + scrambling_work); > + > + if (drm_scdc_get_scrambling_status(vc4_hdmi->ddc)) > + return; > + > + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); > + drm_scdc_set_scrambling(vc4_hdmi->ddc, true); > + > + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, > + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); > +} > + > static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, > struct drm_atomic_state *state) > { > @@ -2031,6 +2055,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) > vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); > if (!vc4_hdmi) > return -ENOMEM; > + INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); > > dev_set_drvdata(dev, vc4_hdmi); > encoder = &vc4_hdmi->encoder.base.base; > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h > index 3cd021136402..00efcf291c5a 100644 > --- a/drivers/gpu/drm/vc4/vc4_hdmi.h > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h > @@ -126,6 +126,8 @@ struct vc4_hdmi { > struct vc4_hdmi_encoder encoder; > struct drm_connector connector; > > + struct delayed_work scrambling_work; > + > struct i2c_adapter *ddc; > void __iomem *hdmicore_regs; > void __iomem *hd_regs; > -- > 2.31.1 >