[RFC PATCH 6/7] drm: add new drm_mode_connector_get_edid to do drm_get_edid and friends

Jani Nikula jani.nikula at intel.com
Tue Dec 27 16:21:53 UTC 2016


Add a replacement for drm_get_edid that handles override and firmware
EDID at the low level, and handles EDID property update, ELD update, and
adds modes. This allows for a more transparent EDID override, and makes
it possible to unify the drivers better. It also allows reusing the EDID
cached in the property, and only probing the DDC.

Signed-off-by: Jani Nikula <jani.nikula at intel.com>
---
 drivers/gpu/drm/drm_connector.c    | 60 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_probe_helper.c |  7 +++++
 include/drm/drm_connector.h        |  6 ++++
 3 files changed, 73 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 3115db2ae6b1..b9636c98dbf3 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1086,6 +1086,66 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 
+/**
+ * drm_mode_connector_get_edid - do it all replacement for drm_get_edid()
+ * @connector: connector to probe
+ * @adapter: I2C adapter to use for DDC
+ * @edid_out: if non-NULL, get EDID here, must be kfree'd by caller
+ * @no_cache: false to allow using cached EDID, true to force read
+ *
+ * drm_get_edid() on steroids. Handle debugfs override edid, firmware edid, and
+ * caching at the low level. Add modes, update ELD and EDID property. Using this
+ * prevents override/firmware edid usage at the higher level.
+ *
+ * @return: Number of modes from drm_add_edid_modes().
+ */
+int drm_mode_connector_get_edid(struct drm_connector *connector,
+				struct i2c_adapter *adapter,
+				struct edid **edid_out,
+				bool no_cache)
+{
+	struct drm_property_blob *prop = connector->edid_blob_ptr;
+	struct edid *edid = NULL;
+	int count = 0;
+
+	/*
+	 * If a driver uses this function on a connector, override/firmware edid
+	 * will only be used at this level.
+	 */
+	connector->low_level_override = true;
+
+	if ((connector->override_edid || !no_cache) && prop && prop->data)
+		edid = drm_edid_duplicate((struct edid *) prop->data);
+
+	if (!edid) {
+		edid = drm_load_edid_firmware(connector);
+		if (IS_ERR(edid))
+			edid = NULL;
+	}
+
+	if (edid) {
+		/* Require successful probe for override/cached/firmware EDID */
+		if (drm_probe_ddc(adapter))
+			drm_get_displayid(connector, edid);
+		else
+			edid = NULL;
+	} else {
+		edid = drm_get_edid(connector, adapter);
+	}
+
+	count = drm_add_edid_modes(connector, edid);
+	drm_edid_to_eld(connector, edid);
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	if (edid_out)
+		*edid_out = edid;
+	else
+		kfree(edid);
+
+	return count;
+}
+EXPORT_SYMBOL(drm_mode_connector_get_edid);
+
 int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
 				    struct drm_property *property,
 				    uint64_t value)
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 431349673846..20a175a775d6 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -167,6 +167,13 @@ static bool bypass_edid(struct drm_connector *connector, int *count)
 {
 	struct edid *edid;
 
+	/*
+	 * If a driver uses drm_connector_get_edid() on a connector,
+	 * override/firmware edid will only be used at that level.
+	 */
+	if (connector->low_level_override)
+		return false;
+
 	if (connector->override_edid) {
 		edid = (struct edid *) connector->edid_blob_ptr->data;
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 6e352a0b5c81..0c85ddc422de 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/i2c.h>
 #include <drm/drm_mode_object.h>
 
 #include <uapi/drm/drm_mode.h>
@@ -727,6 +728,7 @@ struct drm_connector {
 	/* forced on connector */
 	struct drm_cmdline_mode cmdline_mode;
 	enum drm_connector_force force;
+	bool low_level_override;
 	bool override_edid;
 
 #define DRM_CONNECTOR_MAX_ENCODER 3
@@ -837,6 +839,10 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
 int drm_mode_connector_set_tile_property(struct drm_connector *connector);
 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 					    const struct edid *edid);
+int drm_mode_connector_get_edid(struct drm_connector *connector,
+				struct i2c_adapter *adapter,
+				struct edid **edid_out,
+				bool no_cache);
 
 /**
  * struct drm_tile_group - Tile group metadata
-- 
2.1.4



More information about the dri-devel mailing list