[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