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 6538c46..cafbc37 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; }; /** @@ -2117,30 +2118,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. * @@ -2155,6 +2145,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)) @@ -2175,11 +2169,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); } } @@ -2191,12 +2184,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; @@ -2236,16 +2233,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; @@ -2309,6 +2304,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)) @@ -2316,6 +2312,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