Commit cd004b3f authored by Shirish S's avatar Shirish S Committed by Dave Airlie

drm: edid: add support for E-DDC

The current logic for probing ddc is limited to
2 blocks (256 bytes), this patch adds support
for the 4 block (512) data.

To do this, a single 8-bit segment index is
passed to the display via the I2C address 30h.
Data from the selected segment is then immediately
read via the regular DDC2 address using a repeated
I2C 'START' signal.
Signed-off-by: default avatarShirish S <s.shirish@samsung.com>
Reviewed-by: default avatarJean Delvare <jdelvare@suse.de>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarVille Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 93eb58d5
...@@ -254,6 +254,8 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, ...@@ -254,6 +254,8 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
int block, int len) int block, int len)
{ {
unsigned char start = block * EDID_LENGTH; unsigned char start = block * EDID_LENGTH;
unsigned char segment = block >> 1;
unsigned char xfers = segment ? 3 : 2;
int ret, retries = 5; int ret, retries = 5;
/* The core i2c driver will automatically retry the transfer if the /* The core i2c driver will automatically retry the transfer if the
...@@ -265,6 +267,11 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, ...@@ -265,6 +267,11 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
do { do {
struct i2c_msg msgs[] = { struct i2c_msg msgs[] = {
{ {
.addr = DDC_SEGMENT_ADDR,
.flags = 0,
.len = 1,
.buf = &segment,
}, {
.addr = DDC_ADDR, .addr = DDC_ADDR,
.flags = 0, .flags = 0,
.len = 1, .len = 1,
...@@ -276,15 +283,21 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, ...@@ -276,15 +283,21 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
.buf = buf, .buf = buf,
} }
}; };
ret = i2c_transfer(adapter, msgs, 2);
/*
* Avoid sending the segment addr to not upset non-compliant ddc
* monitors.
*/
ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);
if (ret == -ENXIO) { if (ret == -ENXIO) {
DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n", DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",
adapter->name); adapter->name);
break; break;
} }
} while (ret != 2 && --retries); } while (ret != xfers && --retries);
return ret == 2 ? 0 : -1; return ret == xfers ? 0 : -1;
} }
static bool drm_edid_is_zero(u8 *in_edid, int length) static bool drm_edid_is_zero(u8 *in_edid, int length)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment