[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