Merge tag 'drm-misc-next-2018-02-13' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-block.git] / drivers / gpu / drm / i915 / intel_hdmi.c
index 8a9a925410e5686401e69347fada0dde01adbfa1..23150f598dfa77a6742a0ae410e1bba84cf7d444 100644 (file)
@@ -1564,7 +1564,10 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
         * there's nothing connected to the port.
         */
        if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
-               if (has_edid &&
+               /* An overridden EDID imply that we want this port for testing.
+                * Make sure not to set limits for that port.
+                */
+               if (has_edid && !connector->override_edid &&
                    intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
                        DRM_DEBUG_KMS("Assuming DP dual mode adaptor presence based on VBT\n");
                        type = DRM_DP_DUAL_MODE_TYPE1_DVI;
@@ -1592,12 +1595,20 @@ intel_hdmi_set_edid(struct drm_connector *connector)
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
        struct edid *edid;
        bool connected = false;
+       struct i2c_adapter *i2c;
 
        intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
-       edid = drm_get_edid(connector,
-                           intel_gmbus_get_adapter(dev_priv,
-                           intel_hdmi->ddc_bus));
+       i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+       edid = drm_get_edid(connector, i2c);
+
+       if (!edid && !intel_gmbus_is_forced_bit(i2c)) {
+               DRM_DEBUG_KMS("HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n");
+               intel_gmbus_force_bit(i2c, true);
+               edid = drm_get_edid(connector, i2c);
+               intel_gmbus_force_bit(i2c, false);
+       }
 
        intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
 
@@ -1921,6 +1932,9 @@ static u8 cnp_port_to_ddc_pin(struct drm_i915_private *dev_priv,
        case PORT_D:
                ddc_pin = GMBUS_PIN_4_CNP;
                break;
+       case PORT_F:
+               ddc_pin = GMBUS_PIN_3_BXT;
+               break;
        default:
                MISSING_CASE(port);
                ddc_pin = GMBUS_PIN_1_BXT;
@@ -1929,6 +1943,37 @@ static u8 cnp_port_to_ddc_pin(struct drm_i915_private *dev_priv,
        return ddc_pin;
 }
 
+static u8 icl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port)
+{
+       u8 ddc_pin;
+
+       switch (port) {
+       case PORT_A:
+               ddc_pin = GMBUS_PIN_1_BXT;
+               break;
+       case PORT_B:
+               ddc_pin = GMBUS_PIN_2_BXT;
+               break;
+       case PORT_C:
+               ddc_pin = GMBUS_PIN_9_TC1_ICP;
+               break;
+       case PORT_D:
+               ddc_pin = GMBUS_PIN_10_TC2_ICP;
+               break;
+       case PORT_E:
+               ddc_pin = GMBUS_PIN_11_TC3_ICP;
+               break;
+       case PORT_F:
+               ddc_pin = GMBUS_PIN_12_TC4_ICP;
+               break;
+       default:
+               MISSING_CASE(port);
+               ddc_pin = GMBUS_PIN_2_BXT;
+               break;
+       }
+       return ddc_pin;
+}
+
 static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv,
                              enum port port)
 {
@@ -1971,6 +2016,8 @@ static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv,
                ddc_pin = bxt_port_to_ddc_pin(dev_priv, port);
        else if (HAS_PCH_CNP(dev_priv))
                ddc_pin = cnp_port_to_ddc_pin(dev_priv, port);
+       else if (IS_ICELAKE(dev_priv))
+               ddc_pin = icl_port_to_ddc_pin(dev_priv, port);
        else
                ddc_pin = g4x_port_to_ddc_pin(dev_priv, port);
 
@@ -2041,7 +2088,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 
        if (WARN_ON(port == PORT_A))
                return;
-       intel_encoder->hpd_pin = intel_hpd_pin(port);
+       intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
 
        if (HAS_DDI(dev_priv))
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;