From f0639272d6c8e4706ea6d1b0dbc6eb83eaaff412 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 18 Nov 2013 12:07:29 +0100 Subject: [PATCH] ALSA: hda - Bind with HDMI codec parser automatically If a codec contains only the digital outputs, it's very likely a HDMI/DP codec, which isn't supported by the generic parser but via HDMI codec parser code. Detect such a case and bind with the proper parser object if available. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 27 +++++++++++++++++++++++++++ sound/pci/hda/hda_local.h | 1 + sound/pci/hda/patch_hdmi.c | 9 +++++++++ 3 files changed, 37 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4d3f46329eb5..bada677df8a7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1557,6 +1557,31 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets); +#ifdef CONFIG_SND_HDA_CODEC_HDMI +/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ +static bool is_likely_hdmi_codec(struct hda_codec *codec) +{ + hda_nid_t nid = codec->start_nid; + int i; + + for (i = 0; i < codec->num_nodes; i++, nid++) { + unsigned int wcaps = get_wcaps(codec, nid); + switch (get_wcaps_type(wcaps)) { + case AC_WID_AUD_IN: + return false; /* HDMI parser supports only HDMI out */ + case AC_WID_AUD_OUT: + if (!(wcaps & AC_WCAP_DIGITAL)) + return false; + break; + } + } + return true; +} +#else +/* no HDMI codec parser support */ +#define is_likely_hdmi_codec(codec) false +#endif /* CONFIG_SND_HDA_CODEC_HDMI */ + /** * snd_hda_codec_configure - (Re-)configure the HD-audio codec * @codec: the HDA codec @@ -1582,6 +1607,8 @@ int snd_hda_codec_configure(struct hda_codec *codec) patch = codec->preset->patch; if (!patch) { unload_parser(codec); /* to be sure */ + if (is_likely_hdmi_codec(codec)) + patch = load_parser(codec, snd_hda_parse_hdmi_codec); #ifdef CONFIG_SND_HDA_GENERIC if (!patch) patch = load_parser(codec, snd_hda_parse_generic_codec); diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 4d571a6d9230..da80c5bd7fd4 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -353,6 +353,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, * generic codec parser */ int snd_hda_parse_generic_codec(struct hda_codec *codec); +int snd_hda_parse_hdmi_codec(struct hda_codec *codec); /* * generic proc interface diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 08407bed093e..a6081ed34b88 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -3213,6 +3213,15 @@ static int patch_via_hdmi(struct hda_codec *codec) return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); } +/* + * called from hda_codec.c for generic HDMI support + */ +int snd_hda_parse_hdmi_codec(struct hda_codec *codec) +{ + return patch_generic_hdmi(codec); +} +EXPORT_SYMBOL_HDA(snd_hda_parse_hdmi_codec); + /* * patch entries */