[PATCH] drm/edid: Add support for extension blocks beyond the first

Jean Delvare jdelvare at suse.de
Wed Dec 7 06:11:07 PST 2011


When 2 or more EDID extension blocks are present, segment must be
selected prior to reading the extended EDID block over the DDC
channel. Add support for this.

Signed-off-by: Jean Delvare <jdelvare at suse.de>
Cc: Adam Jackson <ajax at redhat.com>
---
This needs testing by someone with access to such a display.

 drivers/gpu/drm/drm_edid.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

--- linux-3.2-rc3.orig/drivers/gpu/drm/drm_edid.c	2011-11-09 15:53:31.000000000 +0100
+++ linux-3.2-rc3/drivers/gpu/drm/drm_edid.c	2011-12-03 10:12:47.000000000 +0100
@@ -242,7 +242,8 @@ static int
 drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 		      int block, int len)
 {
-	unsigned char start = block * EDID_LENGTH;
+	unsigned char segment = block >> 1;
+	unsigned char start = (block & 0x01) * EDID_LENGTH;
 	int ret, retries = 5;
 
 	/* The core i2c driver will automatically retry the transfer if the
@@ -254,6 +255,11 @@ drm_do_probe_ddc_edid(struct i2c_adapter
 	do {
 		struct i2c_msg msgs[] = {
 			{
+				.addr	= DDC_SEGMENT_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &segment,
+			}, {
 				.addr	= DDC_ADDR,
 				.flags	= 0,
 				.len	= 1,
@@ -265,7 +271,18 @@ drm_do_probe_ddc_edid(struct i2c_adapter
 				.buf	= buf,
 			}
 		};
-		ret = i2c_transfer(adapter, msgs, 2);
+
+		/* Don't write segment if it is 0, for compatibility */
+		if (segment) {
+			ret = i2c_transfer(adapter, msgs, 3);
+			/* The E-DDC specification says that the first ack is
+			 * optional, so retry in ignore-nak mode if we get no
+			 * ack at first.
+			 */
+			if (ret == -ENXIO)
+				msgs[0].flags |= I2C_M_IGNORE_NAK;
+		} else
+			ret = i2c_transfer(adapter, msgs + 1, 2);
 	} while (ret != 2 && --retries);
 
 	return ret == 2 ? 0 : -1;

-- 
Jean Delvare
Suse L3


More information about the dri-devel mailing list