drm/edid: Retry EDID fetch up to four times
authorAdam Jackson <ajax@redhat.com>
Mon, 23 Nov 2009 19:23:05 +0000 (14:23 -0500)
committerDave Airlie <airlied@redhat.com>
Tue, 24 Nov 2009 01:24:22 +0000 (11:24 +1000)
This matches the X server's retry logic.  Note that we'll only retry if
we get a DDC response but fail validation; legitimately disconnected
outputs will bomb out early.

See also: http://bugzilla.redhat.com/532957

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_edid.c

index dd95edf..2820082 100644 (file)
@@ -133,9 +133,6 @@ static bool edid_is_valid(struct edid *edid)
                DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
                goto bad;
        }
-       if (edid->revision > 4)
-               DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
-
        for (i = 0; i < EDID_LENGTH; i++)
                csum += raw_edid[i];
        if (csum) {
@@ -143,6 +140,9 @@ static bool edid_is_valid(struct edid *edid)
                goto bad;
        }
 
+       if (edid->revision > 4)
+               DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
+
        return 1;
 
 bad:
@@ -1060,19 +1060,19 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
                             struct i2c_adapter *adapter,
                             char *buf, int len)
 {
-       int ret;
+       int i;
 
-       ret = drm_do_probe_ddc_edid(adapter, buf, len);
-       if (ret != 0) {
-               goto end;
-       }
-       if (!edid_is_valid((struct edid *)buf)) {
-               dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
-                        drm_get_connector_name(connector));
-               ret = -1;
+       for (i = 0; i < 4; i++) {
+               if (drm_do_probe_ddc_edid(adapter, buf, len))
+                       return -1;
+               if (edid_is_valid((struct edid *)buf))
+                       return 0;
        }
-end:
-       return ret;
+
+       /* repeated checksum failures; warn, but carry on */
+       dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
+                drm_get_connector_name(connector));
+       return -1;
 }
 
 /**