From: Imre Deak <imre.deak@xxxxxxxxx> commit 2f51312bebb77962a518b4c6de777dd378b6110a upstream. The TypeC FIA can be powered down if the TC-COLD power state is allowed, so block the TC-COLD state when initializing the FIA. Note that this isn't needed on ICL where the FIA is never modular and which has no generic way to block TC-COLD (except for platforms with a legacy TypeC port and on those too only via these legacy ports, not via a DP-alt/TBT port). Cc: <stable@xxxxxxxxxxxxxxx> # v5.10+ Cc: José Roberto de Souza <jose.souza@xxxxxxxxx> Reported-by: Paul Menzel <pmenzel@xxxxxxxxxxxxx> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3027 Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> Link: https://patchwork.freedesktop.org/patch/msgid/20210208154303.6839-1-imre.deak@xxxxxxxxx Reviewed-by: Jos� Roberto de Souza <jose.souza@xxxxxxxxx> (cherry picked from commit f48993e5d26b079e8c80fff002499a213dbdb1b4) Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_tc.c | 67 +++++++++++++++++--------------- 1 file changed, 37 insertions(+), 30 deletions(-) --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -23,36 +23,6 @@ static const char *tc_port_mode_name(enu return names[mode]; } -static void -tc_port_load_fia_params(struct drm_i915_private *i915, - struct intel_digital_port *dig_port) -{ - enum port port = dig_port->base.port; - enum tc_port tc_port = intel_port_to_tc(i915, port); - u32 modular_fia; - - if (INTEL_INFO(i915)->display.has_modular_fia) { - modular_fia = intel_uncore_read(&i915->uncore, - PORT_TX_DFLEXDPSP(FIA1)); - drm_WARN_ON(&i915->drm, modular_fia == 0xffffffff); - modular_fia &= MODULAR_FIA_MASK; - } else { - modular_fia = 0; - } - - /* - * Each Modular FIA instance houses 2 TC ports. In SOC that has more - * than two TC ports, there are multiple instances of Modular FIA. - */ - if (modular_fia) { - dig_port->tc_phy_fia = tc_port / 2; - dig_port->tc_phy_fia_idx = tc_port % 2; - } else { - dig_port->tc_phy_fia = FIA1; - dig_port->tc_phy_fia_idx = tc_port; - } -} - static enum intel_display_power_domain tc_cold_get_power_domain(struct intel_digital_port *dig_port) { @@ -646,6 +616,43 @@ void intel_tc_port_put_link(struct intel mutex_unlock(&dig_port->tc_lock); } +static bool +tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig_port) +{ + intel_wakeref_t wakeref; + u32 val; + + if (!INTEL_INFO(i915)->display.has_modular_fia) + return false; + + wakeref = tc_cold_block(dig_port); + val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1)); + tc_cold_unblock(dig_port, wakeref); + + drm_WARN_ON(&i915->drm, val == 0xffffffff); + + return val & MODULAR_FIA_MASK; +} + +static void +tc_port_load_fia_params(struct drm_i915_private *i915, struct intel_digital_port *dig_port) +{ + enum port port = dig_port->base.port; + enum tc_port tc_port = intel_port_to_tc(i915, port); + + /* + * Each Modular FIA instance houses 2 TC ports. In SOC that has more + * than two TC ports, there are multiple instances of Modular FIA. + */ + if (tc_has_modular_fia(i915, dig_port)) { + dig_port->tc_phy_fia = tc_port / 2; + dig_port->tc_phy_fia_idx = tc_port % 2; + } else { + dig_port->tc_phy_fia = FIA1; + dig_port->tc_phy_fia_idx = tc_port; + } +} + void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);