|
@@ -1125,9 +1125,9 @@ EXPORT_SYMBOL(drm_edid_is_valid);
|
|
|
* Return: 0 on success or -1 on failure.
|
|
|
*/
|
|
|
static int
|
|
|
-drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
|
|
|
- int block, int len)
|
|
|
+drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
|
|
|
{
|
|
|
+ struct i2c_adapter *adapter = data;
|
|
|
unsigned char start = block * EDID_LENGTH;
|
|
|
unsigned char segment = block >> 1;
|
|
|
unsigned char xfers = segment ? 3 : 2;
|
|
@@ -1184,8 +1184,26 @@ static bool drm_edid_is_zero(u8 *in_edid, int length)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-static u8 *
|
|
|
-drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|
|
+/**
|
|
|
+ * drm_do_get_edid - get EDID data using a custom EDID block read function
|
|
|
+ * @connector: connector we're probing
|
|
|
+ * @get_edid_block: EDID block read function
|
|
|
+ * @data: private data passed to the block read function
|
|
|
+ *
|
|
|
+ * When the I2C adapter connected to the DDC bus is hidden behind a device that
|
|
|
+ * exposes a different interface to read EDID blocks this function can be used
|
|
|
+ * to get EDID data using a custom block read function.
|
|
|
+ *
|
|
|
+ * As in the general case the DDC bus is accessible by the kernel at the I2C
|
|
|
+ * level, drivers must make all reasonable efforts to expose it as an I2C
|
|
|
+ * adapter and use drm_get_edid() instead of abusing this function.
|
|
|
+ *
|
|
|
+ * Return: Pointer to valid EDID or NULL if we couldn't find any.
|
|
|
+ */
|
|
|
+struct edid *drm_do_get_edid(struct drm_connector *connector,
|
|
|
+ int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
|
|
|
+ size_t len),
|
|
|
+ void *data)
|
|
|
{
|
|
|
int i, j = 0, valid_extensions = 0;
|
|
|
u8 *block, *new;
|
|
@@ -1196,7 +1214,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|
|
|
|
|
/* base block fetch */
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
- if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
|
|
|
+ if (get_edid_block(data, block, 0, EDID_LENGTH))
|
|
|
goto out;
|
|
|
if (drm_edid_block_valid(block, 0, print_bad_edid))
|
|
|
break;
|
|
@@ -1210,7 +1228,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|
|
|
|
|
/* if there's no extensions, we're done */
|
|
|
if (block[0x7e] == 0)
|
|
|
- return block;
|
|
|
+ return (struct edid *)block;
|
|
|
|
|
|
new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
|
|
|
if (!new)
|
|
@@ -1219,7 +1237,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|
|
|
|
|
for (j = 1; j <= block[0x7e]; j++) {
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
- if (drm_do_probe_ddc_edid(adapter,
|
|
|
+ if (get_edid_block(data,
|
|
|
block + (valid_extensions + 1) * EDID_LENGTH,
|
|
|
j, EDID_LENGTH))
|
|
|
goto out;
|
|
@@ -1247,7 +1265,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|
|
block = new;
|
|
|
}
|
|
|
|
|
|
- return block;
|
|
|
+ return (struct edid *)block;
|
|
|
|
|
|
carp:
|
|
|
if (print_bad_edid) {
|
|
@@ -1260,6 +1278,7 @@ out:
|
|
|
kfree(block);
|
|
|
return NULL;
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(drm_do_get_edid);
|
|
|
|
|
|
/**
|
|
|
* drm_probe_ddc() - probe DDC presence
|
|
@@ -1289,12 +1308,10 @@ EXPORT_SYMBOL(drm_probe_ddc);
|
|
|
struct edid *drm_get_edid(struct drm_connector *connector,
|
|
|
struct i2c_adapter *adapter)
|
|
|
{
|
|
|
- struct edid *edid = NULL;
|
|
|
-
|
|
|
- if (drm_probe_ddc(adapter))
|
|
|
- edid = (struct edid *)drm_do_get_edid(connector, adapter);
|
|
|
+ if (!drm_probe_ddc(adapter))
|
|
|
+ return NULL;
|
|
|
|
|
|
- return edid;
|
|
|
+ return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_get_edid);
|
|
|
|