diff mbox

[RFC,v2,2/5] drm/edid: temporarily exposing generic edid-read interface from drm

Message ID 1360238951-7022-1-git-send-email-rahul.sharma@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rahul Sharma Feb. 7, 2013, 12:09 p.m. UTC
It exposes generic interface from drm_edid.c to get the edid data and length
by any display entity. Once I get clear idea about edid handling in CDF, I need
to revert these temporary changes.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
---
 drivers/gpu/drm/drm_edid.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

Comments

Daniel Vetter Feb. 7, 2013, 1:28 p.m. UTC | #1
On Thu, Feb 7, 2013 at 1:09 PM, Rahul Sharma <rahul.sharma@samsung.com> wrote:
> It exposes generic interface from drm_edid.c to get the edid data and length
> by any display entity. Once I get clear idea about edid handling in CDF, I need
> to revert these temporary changes.

Just a quick reply about edid reading: One of the key results (at
least imo) of the fosdem cdf discussion was that we need to split up
the different parts of it clearly (i.e. abstract panel interface, dsi
support, discovery/dev matching, ...) to have more flexibility. One
idea is also to not use the panel interface for e.g. hdmi transcoders,
but only use the bus support (like dsi), since transcoders which
connect to external devices like hdmi need to expose _much_ more
features to the master driver and so it's better to have tighter
integration. Some of the things which need close cooperation between
drivers are e.g. edid reading, hotplug handling,
bpp/colorspace/restricted range stuff, ... I didn't read through the
patch which requires the exported drm edid stuff, but maybe this helps
a bit.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5a3770f..567a565 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -31,6 +31,7 @@ 
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <video/display.h>
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
 #include "drm_edid_modes.h"
@@ -386,6 +387,93 @@  out:
 	return NULL;
 }
 
+int generic_drm_do_get_edid(struct i2c_adapter *adapter,
+	struct display_entity_edid *edid)
+{
+	int i, j = 0, valid_extensions = 0;
+	u8 *block, *new;
+	bool print_bad_edid = 0;
+
+	block = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!block)
+		return -ENOMEM;
+
+	/* base block fetch */
+	for (i = 0; i < 4; i++) {
+		if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
+			goto out;
+		if (drm_edid_block_valid(block, 0, print_bad_edid))
+			break;
+		if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH))
+			goto carp;
+	}
+	if (i == 4)
+		goto carp;
+
+	/* if there's no extensions, we're done */
+	if (block[0x7e] == 0) {
+		edid->edid = block;
+		edid->len = EDID_LENGTH;
+		return 0;
+	}
+
+	new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+	if (!new)
+		goto out;
+	block = new;
+	edid->len = (block[0x7e] + 1) * EDID_LENGTH;
+
+	for (j = 1; j <= block[0x7e]; j++) {
+		for (i = 0; i < 4; i++) {
+			if (drm_do_probe_ddc_edid(adapter,
+				  block + (valid_extensions + 1) * EDID_LENGTH,
+				  j, EDID_LENGTH))
+				goto out;
+			if (drm_edid_block_valid(block + (valid_extensions + 1)*
+				EDID_LENGTH, j, print_bad_edid)) {
+				valid_extensions++;
+				break;
+			}
+		}
+		if (i == 4)
+			DRM_DEBUG_KMS("Ignoring inv lock %d.\n", j);
+	}
+
+	if (valid_extensions != block[0x7e]) {
+		block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
+		block[0x7e] = valid_extensions;
+		new = krealloc(block, (valid_extensions + 1)*
+			EDID_LENGTH, GFP_KERNEL);
+		if (!new)
+			goto out;
+		block = new;
+		edid->len = (valid_extensions + 1) * EDID_LENGTH;
+	}
+
+	edid->edid = block;
+	return 0;
+
+carp:
+	if (print_bad_edid)
+		DRM_DEBUG_KMS("[ERROR]: EDID block %d invalid.\n", j);
+
+out:
+	kfree(block);
+	return -ENOMEM;
+}
+
+
+int generic_drm_get_edid(struct i2c_adapter *adapter,
+	struct display_entity_edid *edid)
+{
+	int ret = -EINVAL;
+	if (drm_probe_ddc(adapter))
+		ret = generic_drm_do_get_edid(adapter, edid);
+
+	return ret;
+}
+EXPORT_SYMBOL(generic_drm_get_edid);
+
 /**
  * Probe DDC presence.
  *