[PATCH 12/14] drm/i915: cache hdmi edid

Daniel Vetter daniel.vetter at ffwll.ch
Thu May 24 12:26:47 PDT 2012


Like the previous patches.

While at it also kill a stale comment - we've moved hdmi audio
detection from ->get_modes to ->detect and the audio property handling
functions.

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/intel_drv.h  |    1 +
 drivers/gpu/drm/i915/intel_hdmi.c |   48 +++++++++++++++++++++++--------------
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3b6f716..8693551 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -301,6 +301,7 @@ struct intel_hdmi {
 	enum hdmi_force_audio force_audio;
 	void (*write_infoframe)(struct drm_encoder *encoder,
 				struct dip_infoframe *frame);
+	struct edid *cached_edid;
 };
 
 static inline struct drm_crtc *
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 2ead3bf..373d252 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -452,19 +452,37 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
 	return true;
 }
 
+struct edid *
+intel_hdmi_get_edid(struct drm_connector *connector)
+{
+	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+
+	if (!intel_hdmi->cached_edid) {
+		struct i2c_adapter *adapter;
+
+		adapter = intel_gmbus_get_adapter(dev_priv,
+						  intel_hdmi->ddc_bus);
+		intel_hdmi->cached_edid = drm_get_edid(connector, adapter);
+	}
+
+	return intel_hdmi->cached_edid;
+}
+
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct edid *edid;
 	enum drm_connector_status status = connector_status_disconnected;
 
+	/* Clean the edid cache. */
+	kfree(intel_hdmi->cached_edid);
+	intel_hdmi->cached_edid = NULL;
+
 	intel_hdmi->has_hdmi_sink = false;
 	intel_hdmi->has_audio = false;
-	edid = drm_get_edid(connector,
-			    intel_gmbus_get_adapter(dev_priv,
-						    intel_hdmi->ddc_bus));
+	edid = intel_hdmi_get_edid(connector);
 
 	if (edid) {
 		if (edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -477,6 +495,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
+	intel_hdmi->cached_edid = edid;
 
 	if (status == connector_status_connected) {
 		if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
@@ -489,29 +508,19 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 
 static int intel_hdmi_get_modes(struct drm_connector *connector)
 {
-	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-	struct drm_i915_private *dev_priv = connector->dev->dev_private;
-
-	/* We should parse the EDID data and find out if it's an HDMI sink so
-	 * we can send audio to it.
-	 */
+	struct edid *edid;
 
-	return intel_ddc_get_modes(connector,
-				   intel_gmbus_get_adapter(dev_priv,
-							   intel_hdmi->ddc_bus));
+	edid = intel_hdmi_get_edid(connector);
+	return intel_edid_get_modes(connector, edid);
 }
 
 static bool
 intel_hdmi_detect_audio(struct drm_connector *connector)
 {
-	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct edid *edid;
 	bool has_audio = false;
 
-	edid = drm_get_edid(connector,
-			    intel_gmbus_get_adapter(dev_priv,
-						    intel_hdmi->ddc_bus));
+	edid = intel_hdmi_get_edid(connector);
 	if (edid) {
 		if (edid->input & DRM_EDID_INPUT_DIGITAL)
 			has_audio = drm_detect_monitor_audio(edid);
@@ -580,8 +589,11 @@ done:
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
+	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
+	kfree(intel_hdmi->cached_edid);
 	kfree(connector);
 }
 
-- 
1.7.7.6



More information about the dri-devel mailing list