Message ID | 20220314225837.42816-3-vinod.govindapillai@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | suppress the wrong long hotplug events | expand |
On Tue, 15 Mar 2022, Vinod Govindapillai <vinod.govindapillai@intel.com> wrote: > From: Mohammed Khajapasha <mohammed.khajapasha@intel.com> > > 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@intel.com> > Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com> > --- > 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,
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,