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