drm/i915/dp: try to read receiver capabilities 3 times when detecting
authorJesse Barnes <jbarnes@virtuousgeek.org>
Thu, 7 Jul 2011 18:11:00 +0000 (11:11 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 7 Jul 2011 20:38:44 +0000 (13:38 -0700)
If ->detect is called too soon after a hot plug event, the sink may not
be ready yet.  So try up to 3 times with 1ms sleeps in between tries to
get the data (spec dictates that receivers must be ready to respond within
1ms and that sources should try 3 times).

See section 9.1 of the 1.1a DisplayPort spec.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
drivers/gpu/drm/i915/intel_dp.c

index a9a5051419dff9cc433f5907fe6ac530d3271fc4..70075d9900da6fc0e748e8e6f7706723e6134fe6 100644 (file)
@@ -1551,6 +1551,7 @@ static enum drm_connector_status
 ironlake_dp_detect(struct intel_dp *intel_dp)
 {
        enum drm_connector_status status;
+       int ret, i;
 
        /* Can't disconnect eDP, but you can close the lid... */
        if (is_edp(intel_dp)) {
@@ -1561,12 +1562,16 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
        }
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_dp,
-                                    0x000, intel_dp->dpcd,
-                                    sizeof (intel_dp->dpcd))
-           == sizeof(intel_dp->dpcd)) {
-               if (intel_dp->dpcd[DP_DPCD_REV] != 0)
+       for (i = 0; i < 3; i++) {
+               ret = intel_dp_aux_native_read(intel_dp,
+                                              0x000, intel_dp->dpcd,
+                                              sizeof (intel_dp->dpcd));
+               if (ret == sizeof(intel_dp->dpcd) &&
+                   intel_dp->dpcd[DP_DPCD_REV] != 0) {
                        status = connector_status_connected;
+                       break;
+               }
+               msleep(1);
        }
        DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
                      intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);