drm/i915/tc: Avoid using legacy AUX PW in TBT mode
authorImre Deak <imre.deak@intel.com>
Wed, 29 Sep 2021 13:28:31 +0000 (16:28 +0300)
committerImre Deak <imre.deak@intel.com>
Wed, 29 Sep 2021 20:57:54 +0000 (23:57 +0300)
For the ADL-P TBT mode the spec doesn't require blocking TC-cold by
using the legacy AUX power domain. To avoid the timeouts that this would
cause during PHY disconnect/reconnect sequences (which will be more
frequent after a follow-up change) use the TC_COLD_OFF power domain in
TBT mode on all platforms. On TGL this power domain blocks TC-cold via a
PUNIT command, while on other platforms the domain just takes a runtime
PM reference.

If the HPD live status indicates that the port mode needs to be reset
- for instance after switching from TBT to a DP-alt sink - still take
the AUX domain, since the IOM firmware handshake requires this.

v2: Rebased on v2 of the previous patch.

Cc: José Roberto de Souza <jose.souza@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210929132833.2253961-5-imre.deak@intel.com
drivers/gpu/drm/i915/display/intel_tc.c

index 69c917f..2df4d0b 100644 (file)
@@ -59,10 +59,10 @@ bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
 static enum intel_display_power_domain
 tc_cold_get_power_domain(struct intel_digital_port *dig_port, enum tc_port_mode mode)
 {
-       if (intel_tc_cold_requires_aux_pw(dig_port))
-               return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
-       else
+       if (mode == TC_PORT_TBT_ALT || !intel_tc_cold_requires_aux_pw(dig_port))
                return POWER_DOMAIN_TC_COLD_OFF;
+
+       return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
 }
 
 static intel_wakeref_t
@@ -645,6 +645,36 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
                    tc_port_mode_name(dig_port->tc_mode));
 }
 
+static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
+{
+       return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode;
+}
+
+static void intel_tc_port_update_mode(struct intel_digital_port *dig_port,
+                                     int required_lanes, bool force_disconnect)
+{
+       enum intel_display_power_domain domain;
+       intel_wakeref_t wref;
+       bool needs_reset = force_disconnect;
+
+       if (!needs_reset) {
+               /* Get power domain required to check the hotplug live status. */
+               wref = tc_cold_block(dig_port, &domain);
+               needs_reset = intel_tc_port_needs_reset(dig_port);
+               tc_cold_unblock(dig_port, domain, wref);
+       }
+
+       if (!needs_reset)
+               return;
+
+       /* Get power domain required for resetting the mode. */
+       wref = tc_cold_block_in_mode(dig_port, TC_PORT_DISCONNECTED, &domain);
+
+       intel_tc_port_reset_mode(dig_port, required_lanes, force_disconnect);
+
+       tc_cold_unblock(dig_port, domain, wref);
+}
+
 static void
 intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
                                 int refcount)
@@ -691,11 +721,6 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
        mutex_unlock(&dig_port->tc_lock);
 }
 
-static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
-{
-       return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode;
-}
-
 /*
  * The type-C ports are different because even when they are connected, they may
  * not be available/usable by the graphics driver: see the comment on
@@ -735,18 +760,10 @@ static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
 
        mutex_lock(&dig_port->tc_lock);
 
-       if (!dig_port->tc_link_refcount) {
-               enum intel_display_power_domain domain;
-               intel_wakeref_t tc_cold_wref;
-
-               tc_cold_wref = tc_cold_block(dig_port, &domain);
 
-               if (force_disconnect || intel_tc_port_needs_reset(dig_port))
-                       intel_tc_port_reset_mode(dig_port, required_lanes,
-                                                force_disconnect);
-
-               tc_cold_unblock(dig_port, domain, tc_cold_wref);
-       }
+       if (!dig_port->tc_link_refcount)
+               intel_tc_port_update_mode(dig_port, required_lanes,
+                                         force_disconnect);
 
        drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref);
        dig_port->tc_lock_wakeref = wakeref;