On Tue, 15 Mar 2022, Vinod Govindapillai <vinod.govindapillai@xxxxxxxxx> wrote: > From: Mohammed Khajapasha <mohammed.khajapasha@xxxxxxxxx> > > Add 2sec sleep for power state connector when a monitor > is in power sleep state before atomic commit enable. We're absolutely not adding a sleep like this. > Monitors like LG 27UL650-W, 27UK850 goes into power > sleep state and generates long duration hotplug events > even the monitor connected for display, sleep for 2sec > for power state monitor become available before enable > atomic commit. Again, will need a better description of the failure mode and/or a detailed bug report to even suggest a better alternative. BR, Jani. > > Signed-off-by: Mohammed Khajapasha <mohammed.khajapasha@xxxxxxxxx> > Signed-off-by: Vinod Govindapillai <vinod.govindapillai@xxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_display.c | 80 ++++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_display.h | 8 ++ > 2 files changed, 88 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index 54db81c2cce6..a793f4234460 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -224,6 +224,81 @@ static int intel_compute_global_watermarks(struct intel_atomic_state *state) > return 0; > } > > +static void > +intel_connectors_wakeup_hpd_suppress(struct intel_atomic_state *state) > +{ > + struct drm_i915_private *i915 = to_i915(state->base.dev); > + struct i915_hotplug *hpd = &i915->hotplug; > + bool do_delay = false; > + struct intel_connector *connector; > + struct intel_digital_connector_state *conn_state; > + int i; > + > + if (!hpd->suppress_wakeup_hpd_enabled) > + return; > + > + for_each_new_intel_connector_in_state(state, connector, > + conn_state, i) { > + struct intel_crtc *crtc = to_intel_crtc(conn_state->base.crtc); > + struct intel_crtc_state *crtc_state; > + > + if (!crtc || !intel_connector_needs_modeset(state, > + &connector->base)) > + continue; > + > + crtc_state = intel_atomic_get_new_crtc_state(state, crtc); > + if (!crtc_state->hw.active) > + continue; > + > + if (!intel_connector_need_suppress_wakeup_hpd(connector)) > + continue; > + > + if (time_is_before_jiffies64(connector->disabled_time + > + msecs_to_jiffies(MSEC_PER_SEC * 10))) { > + drm_dbg_kms(&i915->drm, > + "[CONNECTOR:%d:%s] Suppress wakeup HPD for 2 secs\n", > + connector->base.base.id, connector->base.name); > + do_delay = true; > + } > + } > + > + if (do_delay) > + msleep(2 * MSEC_PER_SEC); > +} > + > +static void > +intel_connectors_wakeup_hpd_track_disabling(struct intel_atomic_state *state) > +{ > + struct drm_i915_private *i915 = to_i915(state->base.dev); > + struct i915_hotplug *hpd = &i915->hotplug; > + struct intel_connector *connector; > + struct intel_digital_connector_state *conn_state; > + int i; > + > + if (!hpd->suppress_wakeup_hpd_enabled) > + return; > + > + for_each_old_intel_connector_in_state(state, connector, > + conn_state, i) { > + struct intel_crtc *crtc = to_intel_crtc(conn_state->base.crtc); > + struct intel_crtc_state *crtc_state; > + > + if (!crtc || !intel_connector_needs_modeset(state, > + &connector->base)) > + continue; > + > + crtc_state = intel_atomic_get_old_crtc_state(state, crtc); > + if (!crtc_state->hw.active) > + continue; > + > + drm_dbg_kms(&i915->drm, > + "[CONNECTOR:%d:%s] Update disabled time for wakeup HPD handling\n", > + connector->base.base.id, connector->base.name); > + > + connector->disabled_time = get_jiffies_64(); > + } > +} > + > /* returns HPLL frequency in kHz */ > int vlv_get_hpll_vco(struct drm_i915_private *dev_priv) > { > @@ -8517,6 +8592,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) > } > } > > + intel_connectors_wakeup_hpd_track_disabling(state); > + > intel_commit_modeset_disables(state); > > /* FIXME: Eventually get rid of our crtc->config pointer */ > @@ -8560,6 +8637,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) > /* Now enable the clocks, plane, pipe, and connectors that we set up. */ > dev_priv->display->commit_modeset_enables(state); > > + /* sleep for 2sec for power state connector become available */ > + intel_connectors_wakeup_hpd_suppress(state); > + > intel_encoders_update_complete(state); > > if (state->modeset) > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h > index 8513703086b7..12ecf1497b07 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.h > +++ b/drivers/gpu/drm/i915/display/intel_display.h > @@ -539,6 +539,14 @@ enum hpd_pin { > ((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \ > (new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1)) > > +#define for_each_old_intel_connector_in_state(__state, connector, old_connector_state, __i) \ > + for ((__i) = 0; \ > + (__i) < (__state)->base.num_connector; \ > + (__i)++) \ > + for_each_if((__state)->base.connectors[__i].ptr && \ > + ((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \ > + (old_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].old_state), 1)) > + > int intel_atomic_add_affected_planes(struct intel_atomic_state *state, > struct intel_crtc *crtc); > u8 intel_calc_active_pipes(struct intel_atomic_state *state, -- Jani Nikula, Intel Open Source Graphics Center