drm: i2c: tda998x: Retry fetching the EDID if it fails first time.
authorLiviu Dudau <Liviu.Dudau@arm.com>
Mon, 21 Jul 2014 11:31:11 +0000 (12:31 +0100)
committerLiviu Dudau <Liviu.Dudau@arm.com>
Mon, 22 Sep 2014 15:14:51 +0000 (16:14 +0100)
Fetching the EDID from a connected monitor is an automated thing
with NXP TDA19988. But on some boards the fetching fails for the
first time silently without any indication that an error has occured.
More than that, subsequent fetches of the EDID succeed until the
monitor(s) are pluged out.

Add a function to validate the read EDID and retry if the block
retrieved is not valid.

Signed-off-by: Andrew Jackson <Andrew.Jackson@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
drivers/gpu/drm/i2c/tda998x_drv.c

index db5440d..27632aa 100644 (file)
@@ -1073,13 +1073,38 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
        return 0;
 }
 
+static int
+read_validate_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+{
+       bool print_bad_edid = drm_debug & DRM_UT_KMS;
+       int ret;
+       int retries = 1;
+
+       do
+       {
+               bool print_bad = print_bad_edid && (retries == 0);
+
+               ret = read_edid_block(encoder, buf, blk);
+               /* Fail on I2C error */
+               if (ret)
+                       break;
+
+               /* But retry checksum errored blocks */
+               if (drm_edid_block_valid(buf, blk, print_bad))
+                       break;
+               else
+                       ret = -EINVAL;
+       } while (retries-- > 0);
+
+       return ret;
+}
+
 static uint8_t *
 do_get_edid(struct drm_encoder *encoder)
 {
        struct tda998x_priv *priv = to_tda998x_priv(encoder);
        int j, valid_extensions = 0;
        uint8_t *block, *new;
-       bool print_bad_edid = drm_debug & DRM_UT_KMS;
 
        if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
                return NULL;
@@ -1088,10 +1113,7 @@ do_get_edid(struct drm_encoder *encoder)
                reg_clear(priv, REG_TX4, TX4_PD_RAM);
 
        /* base block fetch */
-       if (read_edid_block(encoder, block, 0))
-               goto fail;
-
-       if (!drm_edid_block_valid(block, 0, print_bad_edid))
+       if (read_validate_edid_block(encoder, block, 0))
                goto fail;
 
        /* if there's no extensions, we're done */
@@ -1105,10 +1127,7 @@ do_get_edid(struct drm_encoder *encoder)
 
        for (j = 1; j <= block[0x7e]; j++) {
                uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
-               if (read_edid_block(encoder, ext_block, j))
-                       goto fail;
-
-               if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
+               if (read_validate_edid_block(encoder, ext_block, j))
                        goto fail;
 
                valid_extensions++;