[Intel-gfx] [PATCH] drm/i915/icl+: Prevent using non-TypeC AUX channels on TypeC ports
Imre Deak
imre.deak at intel.com
Thu Apr 23 18:19:37 UTC 2020
Using an AUX channel which by default belongs to a non-TypeC PHY won't
work on a TypeC PHY, since - as a side-effect besides providing an AUX
channel - the AUX channel power well affects power manangement specific
to the TypeC subsystem. Using a TypeC AUX channel on a non-TypeC PHY
would probably also cause problems, so for simplicity prevent both.
This fixes at least an ICL-Y machine in CI, which has a buggy VBT
setting AUX-B as an alternative channel for port C.
Signed-off-by: Imre Deak <imre.deak at intel.com>
---
drivers/gpu/drm/i915/display/intel_bios.c | 84 +++++++++++++++--------
1 file changed, 57 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 839124647202..10d463723d12 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1538,11 +1538,38 @@ static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch)
return PORT_NONE;
}
+static enum aux_ch
+intel_bios_port_info_aux_ch(const struct ddi_vbt_port_info *info)
+{
+ switch (info->alternate_aux_channel) {
+ case DP_AUX_A:
+ return AUX_CH_A;
+ case DP_AUX_B:
+ return AUX_CH_B;
+ case DP_AUX_C:
+ return AUX_CH_C;
+ case DP_AUX_D:
+ return AUX_CH_D;
+ case DP_AUX_E:
+ return AUX_CH_E;
+ case DP_AUX_F:
+ return AUX_CH_F;
+ case DP_AUX_G:
+ return AUX_CH_G;
+ default:
+ MISSING_CASE(info->alternate_aux_channel);
+ return AUX_CH_A;
+ }
+}
+
static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
enum port port)
{
struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
enum port p;
+ enum aux_ch aux_ch;
+ bool aux_is_tc;
+ bool phy_is_tc;
if (!info->alternate_aux_channel)
return;
@@ -1571,6 +1598,35 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
info->supports_dp = false;
info->alternate_aux_channel = 0;
+
+ return;
+ }
+
+ aux_ch = intel_bios_port_info_aux_ch(info);
+ /* The AUX CH -> default port is a 1:1 mapping. */
+ aux_is_tc = intel_phy_is_tc(dev_priv,
+ intel_port_to_phy(dev_priv,
+ (enum port)aux_ch));
+ phy_is_tc = intel_phy_is_tc(dev_priv,
+ intel_port_to_phy(dev_priv, port));
+ if (aux_is_tc != phy_is_tc) {
+ /*
+ * Using an AUX channel which by default belongs to a TypeC
+ * PHY can't be used for non-TypeC PHYs and vice-versa. The
+ * reason is that TypeC AUX power wells can only be enabled in
+ * the current TypeC mode of the PHY and have an effect on power
+ * management specific to the TypeC subsystem.
+ */
+ drm_dbg_kms(&dev_priv->drm,
+ "Port %c on a %s PHY is trying to use the %s AUX CH %c, "
+ "disabling DP support on this port.\n",
+ port_name(port),
+ phy_is_tc ? "TypeC" : "non-TypeC",
+ aux_is_tc ? "TypeC" : "non-TypeC",
+ aux_ch_name(aux_ch));
+
+ info->supports_dp = false;
+ info->alternate_aux_channel = 0;
}
}
@@ -2595,33 +2651,7 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
return aux_ch;
}
- switch (info->alternate_aux_channel) {
- case DP_AUX_A:
- aux_ch = AUX_CH_A;
- break;
- case DP_AUX_B:
- aux_ch = AUX_CH_B;
- break;
- case DP_AUX_C:
- aux_ch = AUX_CH_C;
- break;
- case DP_AUX_D:
- aux_ch = AUX_CH_D;
- break;
- case DP_AUX_E:
- aux_ch = AUX_CH_E;
- break;
- case DP_AUX_F:
- aux_ch = AUX_CH_F;
- break;
- case DP_AUX_G:
- aux_ch = AUX_CH_G;
- break;
- default:
- MISSING_CASE(info->alternate_aux_channel);
- aux_ch = AUX_CH_A;
- break;
- }
+ aux_ch = intel_bios_port_info_aux_ch(info);
drm_dbg_kms(&dev_priv->drm, "using AUX %c for port %c (VBT)\n",
aux_ch_name(aux_ch), port_name(port));
--
2.23.1
More information about the Intel-gfx
mailing list