drm/i915: Trigger modesetting if force-audio changes
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 9 Feb 2011 18:46:58 +0000 (18:46 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 11 Feb 2011 09:20:50 +0000 (09:20 +0000)
If the user changes the force-audio property and it no longer reflects
the current configuration, then we need to trigger a mode set in order
to update the registers.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_sdvo.c

index 1f4242b..51cb4e3 100644 (file)
@@ -1639,6 +1639,24 @@ static int intel_dp_get_modes(struct drm_connector *connector)
        return 0;
 }
 
+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 = drm_get_edid(connector, &intel_dp->adapter);
+       if (edid) {
+               has_audio = drm_detect_monitor_audio(edid);
+
+               connector->display_info.raw_edid = NULL;
+               kfree(edid);
+       }
+
+       return has_audio;
+}
+
 static int
 intel_dp_set_property(struct drm_connector *connector,
                      struct drm_property *property,
@@ -1652,17 +1670,23 @@ intel_dp_set_property(struct drm_connector *connector,
                return ret;
 
        if (property == intel_dp->force_audio_property) {
-               if (val == intel_dp->force_audio)
+               int i = val;
+               bool has_audio;
+
+               if (i == intel_dp->force_audio)
                        return 0;
 
-               intel_dp->force_audio = val;
+               intel_dp->force_audio = i;
 
-               if (val > 0 && intel_dp->has_audio)
-                       return 0;
-               if (val < 0 && !intel_dp->has_audio)
+               if (i == 0)
+                       has_audio = intel_dp_detect_audio(connector);
+               else
+                       has_audio = i > 0;
+
+               if (has_audio == intel_dp->has_audio)
                        return 0;
 
-               intel_dp->has_audio = val > 0;
+               intel_dp->has_audio = has_audio;
                goto done;
        }
 
index 0d0273e..c635c9e 100644 (file)
@@ -251,6 +251,27 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
                                   &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
 }
 
+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,
+                           &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
+       if (edid) {
+               if (edid->input & DRM_EDID_INPUT_DIGITAL)
+                       has_audio = drm_detect_monitor_audio(edid);
+
+               connector->display_info.raw_edid = NULL;
+               kfree(edid);
+       }
+
+       return has_audio;
+}
+
 static int
 intel_hdmi_set_property(struct drm_connector *connector,
                      struct drm_property *property,
@@ -264,17 +285,23 @@ intel_hdmi_set_property(struct drm_connector *connector,
                return ret;
 
        if (property == intel_hdmi->force_audio_property) {
-               if (val == intel_hdmi->force_audio)
+               int i = val;
+               bool has_audio;
+
+               if (i == intel_hdmi->force_audio)
                        return 0;
 
-               intel_hdmi->force_audio = val;
+               intel_hdmi->force_audio = i;
 
-               if (val > 0 && intel_hdmi->has_audio)
-                       return 0;
-               if (val < 0 && !intel_hdmi->has_audio)
+               if (i == 0)
+                       has_audio = intel_hdmi_detect_audio(connector);
+               else
+                       has_audio = i > 0;
+
+               if (has_audio == intel_hdmi->has_audio)
                        return 0;
 
-               intel_hdmi->has_audio = val > 0;
+               intel_hdmi->has_audio = has_audio;
                goto done;
        }
 
index d2dd90a..7c50cdc 100644 (file)
@@ -1690,6 +1690,22 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
        kfree(connector);
 }
 
+static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)
+{
+       struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+       struct edid *edid;
+       bool has_audio = false;
+
+       if (!intel_sdvo->is_hdmi)
+               return false;
+
+       edid = intel_sdvo_get_edid(connector);
+       if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL)
+               has_audio = drm_detect_monitor_audio(edid);
+
+       return has_audio;
+}
+
 static int
 intel_sdvo_set_property(struct drm_connector *connector,
                        struct drm_property *property,
@@ -1706,17 +1722,23 @@ intel_sdvo_set_property(struct drm_connector *connector,
                return ret;
 
        if (property == intel_sdvo_connector->force_audio_property) {
-               if (val == intel_sdvo_connector->force_audio)
+               int i = val;
+               bool has_audio;
+
+               if (i == intel_sdvo_connector->force_audio)
                        return 0;
 
-               intel_sdvo_connector->force_audio = val;
+               intel_sdvo_connector->force_audio = i;
 
-               if (val > 0 && intel_sdvo->has_hdmi_audio)
-                       return 0;
-               if (val < 0 && !intel_sdvo->has_hdmi_audio)
+               if (i == 0)
+                       has_audio = intel_sdvo_detect_hdmi_audio(connector);
+               else
+                       has_audio = i > 0;
+
+               if (has_audio == intel_sdvo->has_hdmi_audio)
                        return 0;
 
-               intel_sdvo->has_hdmi_audio = val > 0;
+               intel_sdvo->has_hdmi_audio = has_audio;
                goto done;
        }