From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Stop with the VBT DDC pin sanitation, and instead just check that the appropriate DDC pin is still available when initializing a HDMI connector. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_bios.c | 72 ----------------------- drivers/gpu/drm/i915/display/intel_hdmi.c | 72 +++++++++++++++++++---- 2 files changed, 59 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 1bfbe1382670..682c9cb6a736 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2223,77 +2223,8 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) vbt_pin); return 0; } -static struct intel_encoder * -get_encoder_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin) -{ - struct intel_encoder *encoder; - - if (!ddc_pin) - return NULL; - - for_each_intel_encoder(&i915->drm, encoder) { - const struct intel_bios_encoder_data *devdata = encoder->devdata; - - if (devdata && ddc_pin == devdata->child.ddc_pin) - return encoder; - } - - return NULL; -} - -static void sanitize_ddc_pin(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child = &devdata->child; - struct intel_encoder *other; - u8 mapped_ddc_pin; - - if (!devdata->child.ddc_pin) - return; - - mapped_ddc_pin = map_ddc_pin(i915, devdata->child.ddc_pin); - if (!intel_gmbus_is_valid_pin(i915, mapped_ddc_pin)) { - drm_dbg_kms(&i915->drm, - "Port %c has invalid DDC pin %d, " - "sticking to defaults\n", - port_name(port), mapped_ddc_pin); - devdata->child.ddc_pin = 0; - return; - } - - other = get_encoder_by_ddc_pin(i915, devdata->child.ddc_pin); - if (!other) - return; - - /* - * Pre-HSW uses separate DP and HDMI encoders - * for the same port. Let them pass. - */ - if (!HAS_DDI(i915) && devdata == other->devdata) - return; - - drm_dbg_kms(&i915->drm, - "port %c trying to use the same DDC pin (0x%x) as port %c, " - "disabling port %c DVI/HDMI support\n", - port_name(port), mapped_ddc_pin, - port_name(other->port), port_name(port)); - - /* - * If we have multiple ports supposedly sharing the pin, then dvi/hdmi - * couldn't exist on the shared port. Otherwise they share the same ddc - * pin and system couldn't communicate with them separately. - * - * First successfully initialized encoder wins. - */ - child->device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING; - child->device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; - - child->ddc_pin = 0; -} - static struct intel_encoder * get_encoder_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch) { struct intel_encoder *encoder; @@ -2758,11 +2689,8 @@ void intel_bios_encoder_sanitize(struct intel_bios_encoder_data *devdata, { if (!devdata) return; - if (intel_bios_encoder_supports_dvi(devdata)) - sanitize_ddc_pin(devdata, port); - if (intel_bios_encoder_supports_dp(devdata)) sanitize_aux_ch(devdata, port); } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index e6f887d75a70..99dd9fbe6944 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2848,23 +2848,14 @@ static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv, } return ddc_pin; } -static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) +static u8 intel_hdmi_default_ddc_pin(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = encoder->port; u8 ddc_pin; - ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata); - if (ddc_pin) { - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] Using DDC pin 0x%x (VBT)\n", - encoder->base.base.id, encoder->base.name, - ddc_pin); - return ddc_pin; - } - if (IS_ALDERLAKE_S(dev_priv)) ddc_pin = adls_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) ddc_pin = dg1_port_to_ddc_pin(dev_priv, port); @@ -2884,12 +2875,64 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) ddc_pin = chv_port_to_ddc_pin(dev_priv, port); else ddc_pin = g4x_port_to_ddc_pin(dev_priv, port); - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] Using DDC pin 0x%x (platform default)\n", + return ddc_pin; +} + +static struct intel_encoder * +get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + + for_each_intel_encoder(&i915->drm, other) { + if (other == encoder) + continue; + + if (!intel_encoder_is_dig_port(other)) + continue; + + if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin) + return other; + } + + return NULL; +} + +static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + const char *source; + u8 ddc_pin; + + ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata); + source = "VBT"; + + if (!ddc_pin) { + ddc_pin = intel_hdmi_default_ddc_pin(encoder); + source = "platform default"; + } + + if (!intel_gmbus_is_valid_pin(i915, ddc_pin)) { + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Invalid DDC pin %d\n", + encoder->base.base.id, encoder->base.name, ddc_pin); + return 0; + } + + other = get_encoder_by_ddc_pin(encoder, ddc_pin); + if (other) { + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] DDC pin %d already claimed by [ENCODER:%d:%s]\n", + encoder->base.base.id, encoder->base.name, ddc_pin, + other->base.base.id, other->base.name); + return 0; + } + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] Using DDC pin 0x%x (%s)\n", encoder->base.base.id, encoder->base.name, - ddc_pin); + ddc_pin, source); return ddc_pin; } @@ -2958,8 +3001,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, intel_encoder->base.name)) return; intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder); + if (!intel_hdmi->ddc_bus) + return; + ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); drm_connector_init_with_ddc(dev, connector, &intel_hdmi_connector_funcs, -- 2.39.2