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@xxxxxxx> Cc: Adam Jackson <ajax@xxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel