From 436009b578ab872619350a4c4f2b36c98c7e55a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 23 Oct 2017 10:39:20 -0700 Subject: [PATCH] drm/i915/cnl: Force DDI_A_4_LANES when needed. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit As we faced in BXT, on CNL DDI_A_4_LANES is not set as expected when system is boot with multiple monitors connected. This result in wrong lane setup impacting the max data rate available and consequently blocking modeset on eDP, resulting in a blank screen. Most of CNL SKUs don't support DDI-E. The only SKU that supports DDI-E is the same that supports the full A/E split called DDI-F. Also when DDI-F is used DDI-E cannot be used because they share Interrupts. So DDI-E is almost useless. Anyways let's consider this is possible and rely on VBT for that. This patch was initialy start by Clint, but required many changes including full commit message. So Credits entirely to Clint for finding this. v2: Extract all messy conditions into a helper function as suggested by Ville. Along with simplification I removed the debug message on the working case since now all conditions are grouped. v3: Split the conditions even more as suggested by Ville. Get's cleaner and easier to add new cases in the future. Suggested-by: Clint Taylor Cc: Clint Taylor Cc: Mika Kahola Cc: Jani Nikula Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171023173920.22890-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 933c18f..08f04df 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2711,6 +2711,34 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) return connector; } +static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) +{ + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + + if (dport->port != PORT_A) + return false; + + if (dport->saved_port_bits & DDI_A_4_LANES) + return false; + + /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only + * supported configuration + */ + if (IS_GEN9_LP(dev_priv)) + return true; + + /* Cannonlake: Most of SKUs don't support DDI_E, and the only + * one who does also have a full A/E split called + * DDI_F what makes DDI_E useless. However for this + * case let's trust VBT info. + */ + if (IS_CANNONLAKE(dev_priv) && + !intel_bios_is_port_present(dev_priv, PORT_E)) + return true; + + return false; +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *intel_dig_port; @@ -2820,18 +2848,14 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) } /* - * Bspec says that DDI_A_4_LANES is the only supported configuration - * for Broxton. Yet some BIOS fail to set this bit on port A if eDP - * wasn't lit up at boot. Force this bit on in our internal - * configuration so that we use the proper lane count for our - * calculations. + * Some BIOS might fail to set this bit on port A if eDP + * wasn't lit up at boot. Force this bit set when needed + * so we use the proper lane count for our calculations. */ - if (IS_GEN9_LP(dev_priv) && port == PORT_A) { - if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { - DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); - intel_dig_port->saved_port_bits |= DDI_A_4_LANES; - max_lanes = 4; - } + if (intel_ddi_a_force_4_lanes(intel_dig_port)) { + DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); + intel_dig_port->saved_port_bits |= DDI_A_4_LANES; + max_lanes = 4; } intel_dig_port->max_lanes = max_lanes; -- 2.7.4