Skip to content

Commit a2ccc33

Browse files
ideakjlahtine-intel
authored andcommitted
drm/i915/dp_mst: Fix MST state after a sink reset
In some cases the sink can reset itself after it was configured into MST mode, without the driver noticing the disconnected state. For instance the reset may happen in the middle of a modeset, or the (long) HPD pulse generated may be not long enough for the encoder detect handler to observe the HPD's deasserted state. In this case the sink's DPCD register programmed to enable MST will be reset, while the driver still assumes MST is still enabled. Detect this condition, which will tear down and recreate/re-enable the MST topology. v2: - Add a code comment about adjusting the expected DP_MSTM_CTRL register value for SST + SideBand. (Suraj, Jani) - Print a debug message about detecting the link reset. (Jani) - Verify the DPCD MST state only if it wasn't already determined that the sink is disconnected. Cc: [email protected] Cc: Jani Nikula <[email protected]> Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11195 Reviewed-by: Suraj Kandpal <[email protected]> (v1) Signed-off-by: Imre Deak <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 594cf78) Signed-off-by: Joonas Lahtinen <[email protected]>
1 parent 2955ae8 commit a2ccc33

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

drivers/gpu/drm/i915/display/intel_dp.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5935,6 +5935,18 @@ intel_dp_detect(struct drm_connector *connector,
59355935
else
59365936
status = connector_status_disconnected;
59375937

5938+
if (status != connector_status_disconnected &&
5939+
!intel_dp_mst_verify_dpcd_state(intel_dp))
5940+
/*
5941+
* This requires retrying detection for instance to re-enable
5942+
* the MST mode that got reset via a long HPD pulse. The retry
5943+
* will happen either via the hotplug handler's retry logic,
5944+
* ensured by setting the connector here to SST/disconnected,
5945+
* or via a userspace connector probing in response to the
5946+
* hotplug uevent sent when removing the MST connectors.
5947+
*/
5948+
status = connector_status_disconnected;
5949+
59385950
if (status == connector_status_disconnected) {
59395951
memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
59405952
memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd));

drivers/gpu/drm/i915/display/intel_dp_mst.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,3 +1998,43 @@ bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state,
19981998

19991999
return false;
20002000
}
2001+
2002+
/*
2003+
* intel_dp_mst_verify_dpcd_state - verify the MST SW enabled state wrt. the DPCD
2004+
* @intel_dp: DP port object
2005+
*
2006+
* Verify if @intel_dp's MST enabled SW state matches the corresponding DPCD
2007+
* state. A long HPD pulse - not long enough to be detected as a disconnected
2008+
* state - could've reset the DPCD state, which requires tearing
2009+
* down/recreating the MST topology.
2010+
*
2011+
* Returns %true if the SW MST enabled and DPCD states match, %false
2012+
* otherwise.
2013+
*/
2014+
bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp)
2015+
{
2016+
struct intel_display *display = to_intel_display(intel_dp);
2017+
struct intel_connector *connector = intel_dp->attached_connector;
2018+
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
2019+
struct intel_encoder *encoder = &dig_port->base;
2020+
int ret;
2021+
u8 val;
2022+
2023+
if (!intel_dp->is_mst)
2024+
return true;
2025+
2026+
ret = drm_dp_dpcd_readb(intel_dp->mst_mgr.aux, DP_MSTM_CTRL, &val);
2027+
2028+
/* Adjust the expected register value for SST + SideBand. */
2029+
if (ret < 0 || val != (DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC)) {
2030+
drm_dbg_kms(display->drm,
2031+
"[CONNECTOR:%d:%s][ENCODER:%d:%s] MST mode got reset, removing topology (ret=%d, ctrl=0x%02x)\n",
2032+
connector->base.base.id, connector->base.name,
2033+
encoder->base.base.id, encoder->base.name,
2034+
ret, val);
2035+
2036+
return false;
2037+
}
2038+
2039+
return true;
2040+
}

drivers/gpu/drm/i915/display/intel_dp_mst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
2727
struct intel_link_bw_limits *limits);
2828
bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state,
2929
struct intel_crtc *crtc);
30+
bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp);
3031

3132
#endif /* __INTEL_DP_MST_H__ */

0 commit comments

Comments
 (0)