[PATCH 11/14] drm/i915: cache dp edid

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


Again, let's be slightly more clever here.

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c |   47 ++++++++++++++++++--------------------
 1 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3bbd754..1c84a97 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -67,6 +67,7 @@ struct intel_dp {
 	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
+	struct edid *cached_edid;
 };
 
 /**
@@ -2089,30 +2090,19 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 }
 
 static struct edid *
-intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+intel_dp_get_edid(struct drm_connector *connector)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct edid	*edid;
-
-	ironlake_edp_panel_vdd_on(intel_dp);
-	edid = drm_get_edid(connector, adapter);
-	ironlake_edp_panel_vdd_off(intel_dp, false);
-	return edid;
-}
 
-static int
-intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
-{
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	int	ret;
+	if (!intel_dp->cached_edid) {
+		ironlake_edp_panel_vdd_on(intel_dp);
+		intel_dp->cached_edid = drm_get_edid(connector, &intel_dp->adapter);
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+	}
 
-	ironlake_edp_panel_vdd_on(intel_dp);
-	ret = intel_ddc_get_modes(connector, adapter);
-	ironlake_edp_panel_vdd_off(intel_dp, false);
-	return ret;
+	return intel_dp->cached_edid;
 }
 
-
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
  *
@@ -2127,6 +2117,10 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
 
+	/* Clean the edid cache. */
+	kfree(intel_dp->cached_edid);
+	intel_dp->cached_edid = NULL;
+
 	intel_dp->has_audio = false;
 
 	if (HAS_PCH_SPLIT(dev))
@@ -2145,11 +2139,10 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
 		intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
 	} else {
-		edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+		edid = intel_dp_get_edid(connector);
 		if (edid) {
 			intel_dp->has_audio = drm_detect_monitor_audio(edid);
 			connector->display_info.raw_edid = NULL;
-			kfree(edid);
 		}
 	}
 
@@ -2161,12 +2154,16 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
+	struct edid	*edid;
+	int ret = 0;
 
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
-	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
+	edid = intel_dp_get_edid(connector);
+	if (edid)
+		ret = intel_edid_get_modes(connector, edid);
+
 	if (ret) {
 		if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
 			struct drm_display_mode *newmode;
@@ -2206,16 +2203,14 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 static bool
 intel_dp_detect_audio(struct drm_connector *connector)
 {
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct edid *edid;
 	bool has_audio = false;
 
-	edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+	edid = intel_dp_get_edid(connector);
 	if (edid) {
 		has_audio = drm_detect_monitor_audio(edid);
 
 		connector->display_info.raw_edid = NULL;
-		kfree(edid);
 	}
 
 	return has_audio;
@@ -2279,6 +2274,7 @@ done:
 static void
 intel_dp_destroy(struct drm_connector *connector)
 {
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct drm_device *dev = connector->dev;
 
 	if (intel_dpd_is_edp(dev))
@@ -2286,6 +2282,7 @@ intel_dp_destroy(struct drm_connector *connector)
 
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
+	kfree(intel_dp->cached_edid);
 	kfree(connector);
 }
 
-- 
1.7.7.6



More information about the dri-devel mailing list