This is a note to let you know that I've just added the patch titled drm/i915/tc: Fix system resume MST mode restore for DP-alt sinks to the 6.1-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch and it can be found in the queue-6.1 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 06f66261a1567d66b9d35c87393b6edfbea4c8f8 Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@xxxxxxxxx> Date: Thu, 16 Mar 2023 15:17:14 +0200 Subject: drm/i915/tc: Fix system resume MST mode restore for DP-alt sinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Imre Deak <imre.deak@xxxxxxxxx> commit 06f66261a1567d66b9d35c87393b6edfbea4c8f8 upstream. At least restoring the MST topology during system resume needs to use AUX before the display HW readout->sanitization sequence is complete, but on TC ports the PHY may be in the wrong mode for this, resulting in the AUX transfers to fail. The initial TC port mode is kept fixed as BIOS left it for the above HW readout sequence (to prevent changing the mode on an enabled port). If the port is disabled this initial mode is TBT - as in any case the PHY ownership is not held - even if a DP-alt sink is connected. Thus, the AUX transfers during this time will use TBT mode instead of the expected DP-alt mode and so time out. Fix the above by connecting the PHY during port initialization if the port is disabled, which will switch to the expected mode (DP-alt in the above case). As the encoder/pipe HW state isn't read-out yet at this point, check if the port is enabled based on the DDI_BUF enabled flag. Save the read-out initial mode, so intel_tc_port_sanitize_mode() can check this wrt. the read-out encoder HW state. Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> Reviewed-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Link: https://patchwork.freedesktop.org/patch/msgid/20230316131724.359612-5-imre.deak@xxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_display_types.h | 1 drivers/gpu/drm/i915/display/intel_tc.c | 49 +++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1763,6 +1763,7 @@ struct intel_digital_port { bool tc_legacy_port:1; char tc_port_name[8]; enum tc_port_mode tc_mode; + enum tc_port_mode tc_init_mode; enum phy_fia tc_phy_fia; u8 tc_phy_fia_idx; --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -5,6 +5,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_de.h" #include "intel_display.h" #include "intel_display_power_map.h" #include "intel_display_types.h" @@ -116,6 +117,24 @@ assert_tc_cold_blocked(struct intel_digi drm_WARN_ON(&i915->drm, !enabled); } +static enum intel_display_power_domain +tc_port_power_domain(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); + + return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; +} + +static void +assert_tc_port_power_enabled(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + + drm_WARN_ON(&i915->drm, + !intel_display_power_is_enabled(i915, tc_port_power_domain(dig_port))); +} + u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); @@ -693,6 +712,16 @@ static void __intel_tc_port_put_link(str dig_port->tc_link_refcount--; } +static bool tc_port_is_enabled(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + + assert_tc_port_power_enabled(dig_port); + + return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & + DDI_BUF_CTL_ENABLE; +} + /** * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode * @dig_port: digital port @@ -715,9 +744,23 @@ void intel_tc_port_init_mode(struct inte tc_cold_wref = tc_cold_block(dig_port, &domain); dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); + /* + * Save the initial mode for the state check in + * intel_tc_port_sanitize_mode(). + */ + dig_port->tc_init_mode = dig_port->tc_mode; + dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); + + /* + * The PHY needs to be connected for AUX to work during HW readout and + * MST topology resume, but the PHY mode can only be changed if the + * port is disabled. + */ + if (!tc_port_is_enabled(dig_port)) + intel_tc_port_update_mode(dig_port, 1, false); + /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ __intel_tc_port_get_link(dig_port); - dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); tc_cold_unblock(dig_port, domain, tc_cold_wref); @@ -764,11 +807,11 @@ void intel_tc_port_sanitize_mode(struct * we'll just switch to disconnected mode from it here without * a note. */ - if (dig_port->tc_mode != TC_PORT_TBT_ALT) + if (dig_port->tc_init_mode != TC_PORT_TBT_ALT) drm_dbg_kms(&i915->drm, "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", dig_port->tc_port_name, - tc_port_mode_name(dig_port->tc_mode)); + tc_port_mode_name(dig_port->tc_init_mode)); icl_tc_phy_disconnect(dig_port); __intel_tc_port_put_link(dig_port); Patches currently in stable-queue which might be from imre.deak@xxxxxxxxx are queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch