diff options
| author | Shirish S <s.shirish@samsung.com> | 2012-08-30 07:04:06 +0000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-09-13 11:28:59 +1000 | 
| commit | cd004b3f4cd4169815c82bf9e424fda06978898a (patch) | |
| tree | 937c4b7676e7f375bb3cc6ad9833b17123a10c13 | |
| parent | 93eb58d53fb14e9eeb1b42f8c04dbd7afc09adf7 (diff) | |
| download | olio-linux-3.10-cd004b3f4cd4169815c82bf9e424fda06978898a.tar.xz olio-linux-3.10-cd004b3f4cd4169815c82bf9e424fda06978898a.zip  | |
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: Shirish S <s.shirish@samsung.com>
Reviewed-by: Jean Delvare <jdelvare@suse.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 19 | 
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 265a0862a96..acb489ff363 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -254,6 +254,8 @@ 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 xfers = segment ? 3 : 2;  	int ret, retries = 5;  	/* 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,  	do {  		struct i2c_msg msgs[] = {  			{ +				.addr	= DDC_SEGMENT_ADDR, +				.flags	= 0, +				.len	= 1, +				.buf	= &segment, +			}, {  				.addr	= DDC_ADDR,  				.flags	= 0,  				.len	= 1, @@ -276,15 +283,21 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *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) {  			DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",  					adapter->name);  			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)  |