Wake up DP sinks for DPCD read-based detection.
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index 9837f90..239f142 100644 (file)
@@ -1248,14 +1248,10 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
 }
 
 /* If the sink supports it, try to set the power state appropriately */
-static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+static void intel_dp_do_sink_dpms(struct intel_dp *intel_dp, int mode)
 {
        int ret, i;
 
-       /* Should have a valid DPCD by this point */
-       if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
-               return;
-
        if (mode != DRM_MODE_DPMS_ON) {
                ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
                                                  DP_SET_POWER_D3);
@@ -1277,6 +1273,16 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
        }
 }
 
+/* If we have a valid DPCD, set the power state. */
+static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+{
+       /* Should have a valid DPCD by this point */
+       if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
+               return;
+
+       intel_dp_do_sink_dpms(intel_dp, mode);
+}
+
 static void intel_dp_prepare(struct drm_encoder *encoder)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -2154,6 +2160,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
        intel_dp->has_audio = false;
 
+       /* Ensure the sink is awake for DPCD/EDID reads. */
+       if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) {
+               /* Bypass DPCD check, since we obtain it during detection. */
+               intel_dp_do_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+       }
+
        if (HAS_PCH_SPLIT(dev))
                status = ironlake_dp_detect(intel_dp);
        else
@@ -2164,8 +2176,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                      intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5],
                      intel_dp->dpcd[6], intel_dp->dpcd[7]);
 
-       if (status != connector_status_connected)
+       if (status != connector_status_connected) {
+               if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+                       intel_dp_do_sink_dpms(intel_dp, intel_dp->dpms_mode);
                return status;
+       }
 
        if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
                intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
@@ -2178,6 +2193,9 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                }
        }
 
+       if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+               intel_dp_do_sink_dpms(intel_dp, intel_dp->dpms_mode);
+
        return connector_status_connected;
 }