From: Ville Syrjälä <ville.syrj...@linux.intel.com>

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.syrj...@linux.intel.com>
---
 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

Reply via email to