diff options
author | Imre Deak <imre.deak@intel.com> | 2021-06-10 20:42:23 +0300 |
---|---|---|
committer | Imre Deak <imre.deak@intel.com> | 2021-06-16 19:13:43 +0300 |
commit | 151ec347b06a2fb6ecd2922475dca71a7af827a5 (patch) | |
tree | 3c740cb0b943fad7ecb1da0aec6ff7caba317dfa /drivers/gpu/drm/i915/display/intel_ddi.c | |
parent | 544021e3f2aa3c4c6c5aabc58907e8bab69b3762 (diff) | |
download | linux-151ec347b06a2fb6ecd2922475dca71a7af827a5.tar.gz linux-151ec347b06a2fb6ecd2922475dca71a7af827a5.tar.bz2 linux-151ec347b06a2fb6ecd2922475dca71a7af827a5.zip |
drm/i915: Force a TypeC PHY disconnect during suspend/shutdown
Disconnect TypeC PHYs during system suspend and shutdown, even with the
corresponding TypeC sink still plugged to its connector, since leaving
the PHY connected causes havoc at least during system resume in the
presence of an Nvidia card.
Note that this will only make a difference in the TypeC DP alternate
mode, since in Thunderbolt alternate mode the PHY is never owned by the
display engine and there is no notion of PHY ownership in legacy mode
(the display engine being the only possible owner in that mode and the
TypeC subsystem not having anything to do with the port in that case).
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3500
Reported-and-tested-by: Chris Chiu <chris.chiu@canonical.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210610174223.605904-1-imre.deak@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_ddi.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0b7fef527e20..637286fbb847 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4497,6 +4497,36 @@ static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port) return false; } +static void intel_ddi_encoder_suspend(struct intel_encoder *encoder) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + enum phy phy = intel_port_to_phy(i915, encoder->port); + + intel_dp_encoder_suspend(encoder); + + if (!intel_phy_is_tc(i915, phy)) + return; + + intel_tc_port_disconnect_phy(dig_port); +} + +static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + enum phy phy = intel_port_to_phy(i915, encoder->port); + + intel_dp_encoder_shutdown(encoder); + + if (!intel_phy_is_tc(i915, phy)) + return; + + intel_tc_port_disconnect_phy(dig_port); +} + #define port_tc_name(port) ((port) - PORT_TC1 + '1') #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1') @@ -4606,8 +4636,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->get_hw_state = intel_ddi_get_hw_state; encoder->sync_state = intel_ddi_sync_state; encoder->initial_fastset_check = intel_ddi_initial_fastset_check; - encoder->suspend = intel_dp_encoder_suspend; - encoder->shutdown = intel_dp_encoder_shutdown; + encoder->suspend = intel_ddi_encoder_suspend; + encoder->shutdown = intel_ddi_encoder_shutdown; encoder->get_power_domains = intel_ddi_get_power_domains; encoder->type = INTEL_OUTPUT_DDI; |