drm/i915: add a "force-dvi" HDMI audio mode

When HDMI-DVI converter is used, it's not only necessary to turn off
audio, but also to disable HDMI_MODE_SELECT and video infoframe. Since
the DVI mode is mainly tied to audio functionality from end user POV,
add a new "force-dvi" audio mode:

	xrandr --output HDMI1 --set audio force-dvi

Note that most users won't need to set this and happily rely on the EDID
based DVI auto detection.

Reported-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Wu Fengguang 2012-02-14 11:45:36 +08:00 committed by Daniel Vetter
parent 8ac5a6d5b5
commit b1d7e4b41f
3 changed files with 22 additions and 10 deletions

View File

@ -762,6 +762,13 @@ typedef struct drm_i915_private {
struct drm_property *force_audio_property; struct drm_property *force_audio_property;
} drm_i915_private_t; } drm_i915_private_t;
enum hdmi_force_audio {
HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */
HDMI_AUDIO_OFF, /* force turn off HDMI audio */
HDMI_AUDIO_AUTO, /* trust EDID */
HDMI_AUDIO_ON, /* force turn on HDMI audio */
};
enum i915_cache_level { enum i915_cache_level {
I915_CACHE_NONE, I915_CACHE_NONE,
I915_CACHE_LLC, I915_CACHE_LLC,

View File

@ -44,7 +44,7 @@ struct intel_hdmi {
uint32_t color_range; uint32_t color_range;
bool has_hdmi_sink; bool has_hdmi_sink;
bool has_audio; bool has_audio;
int force_audio; enum hdmi_force_audio force_audio;
void (*write_infoframe)(struct drm_encoder *encoder, void (*write_infoframe)(struct drm_encoder *encoder,
struct dip_infoframe *frame); struct dip_infoframe *frame);
}; };
@ -339,7 +339,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
if (edid) { if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { if (edid->input & DRM_EDID_INPUT_DIGITAL) {
status = connector_status_connected; status = connector_status_connected;
intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI)
intel_hdmi->has_hdmi_sink =
drm_detect_hdmi_monitor(edid);
intel_hdmi->has_audio = drm_detect_monitor_audio(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
} }
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
@ -347,8 +349,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
} }
if (status == connector_status_connected) { if (status == connector_status_connected) {
if (intel_hdmi->force_audio) if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
intel_hdmi->has_audio = intel_hdmi->force_audio > 0; intel_hdmi->has_audio =
(intel_hdmi->force_audio == HDMI_AUDIO_ON);
} }
return status; return status;
@ -402,7 +405,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
return ret; return ret;
if (property == dev_priv->force_audio_property) { if (property == dev_priv->force_audio_property) {
int i = val; enum hdmi_force_audio i = val;
bool has_audio; bool has_audio;
if (i == intel_hdmi->force_audio) if (i == intel_hdmi->force_audio)
@ -410,13 +413,13 @@ intel_hdmi_set_property(struct drm_connector *connector,
intel_hdmi->force_audio = i; intel_hdmi->force_audio = i;
if (i == 0) if (i == HDMI_AUDIO_AUTO)
has_audio = intel_hdmi_detect_audio(connector); has_audio = intel_hdmi_detect_audio(connector);
else else
has_audio = i > 0; has_audio = (i == HDMI_AUDIO_ON);
if (has_audio == intel_hdmi->has_audio) if (i == HDMI_AUDIO_OFF_DVI)
return 0; intel_hdmi->has_hdmi_sink = 0;
intel_hdmi->has_audio = has_audio; intel_hdmi->has_audio = has_audio;
goto done; goto done;

View File

@ -84,6 +84,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
} }
static const char *force_audio_names[] = { static const char *force_audio_names[] = {
"force-dvi",
"off", "off",
"auto", "auto",
"on", "on",
@ -106,7 +107,8 @@ intel_attach_force_audio_property(struct drm_connector *connector)
return; return;
for (i = 0; i < ARRAY_SIZE(force_audio_names); i++) for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
drm_property_add_enum(prop, i, i-1, force_audio_names[i]); drm_property_add_enum(prop, i, i-2,
force_audio_names[i]);
dev_priv->force_audio_property = prop; dev_priv->force_audio_property = prop;
} }