diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-09-08 09:30:49 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-09-08 09:48:29 -0400 |
commit | bb35febd16fe5ac8c30f9116a25210c4f63a5267 (patch) | |
tree | 72e476187fb90cdc27767c3b9962c764c54ccf59 | |
parent | 03642c9a444079aa13f0864383a8f9ca04bfd198 (diff) |
ALSA: hda - Support multiple headphone auto-mute
Currently headphone auto-mute using alc_automute_pin() assumes only
the single pin used for the headphone output. Since there are devices
with multiple headphone jacks, we need to check all these pins there,
too.
Also this patch merges the common code between alc_automute_pin() and
alc_automute_amp() helper functions.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 92 |
1 files changed, 50 insertions, 42 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 81e4b1d957c5..ee59df7a41f8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -990,25 +990,46 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
990 | alc_fix_pll(codec); | 990 | alc_fix_pll(codec); |
991 | } | 991 | } |
992 | 992 | ||
993 | static void alc_automute_pin(struct hda_codec *codec) | 993 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) |
994 | { | 994 | { |
995 | struct alc_spec *spec = codec->spec; | 995 | struct alc_spec *spec = codec->spec; |
996 | unsigned int nid = spec->autocfg.hp_pins[0]; | 996 | unsigned int mute; |
997 | hda_nid_t nid; | ||
997 | int i; | 998 | int i; |
998 | 999 | ||
999 | if (!nid) | 1000 | spec->jack_present = 0; |
1000 | return; | 1001 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
1001 | spec->jack_present = snd_hda_jack_detect(codec, nid); | 1002 | nid = spec->autocfg.hp_pins[i]; |
1003 | if (!nid) | ||
1004 | break; | ||
1005 | if (snd_hda_jack_detect(codec, nid)) { | ||
1006 | spec->jack_present = 1; | ||
1007 | break; | ||
1008 | } | ||
1009 | } | ||
1010 | |||
1011 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1012 | /* Toggle internal speakers muting */ | ||
1002 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | 1013 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
1003 | nid = spec->autocfg.speaker_pins[i]; | 1014 | nid = spec->autocfg.speaker_pins[i]; |
1004 | if (!nid) | 1015 | if (!nid) |
1005 | break; | 1016 | break; |
1006 | snd_hda_codec_write(codec, nid, 0, | 1017 | if (pinctl) { |
1018 | snd_hda_codec_write(codec, nid, 0, | ||
1007 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1019 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1008 | spec->jack_present ? 0 : PIN_OUT); | 1020 | spec->jack_present ? 0 : PIN_OUT); |
1021 | } else { | ||
1022 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1023 | HDA_AMP_MUTE, mute); | ||
1024 | } | ||
1009 | } | 1025 | } |
1010 | } | 1026 | } |
1011 | 1027 | ||
1028 | static void alc_automute_pin(struct hda_codec *codec) | ||
1029 | { | ||
1030 | alc_automute_speaker(codec, 1); | ||
1031 | } | ||
1032 | |||
1012 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 1033 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, |
1013 | hda_nid_t nid) | 1034 | hda_nid_t nid) |
1014 | { | 1035 | { |
@@ -1236,24 +1257,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
1236 | static void alc_init_auto_hp(struct hda_codec *codec) | 1257 | static void alc_init_auto_hp(struct hda_codec *codec) |
1237 | { | 1258 | { |
1238 | struct alc_spec *spec = codec->spec; | 1259 | struct alc_spec *spec = codec->spec; |
1260 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1261 | int i; | ||
1239 | 1262 | ||
1240 | if (!spec->autocfg.hp_pins[0]) | 1263 | if (!cfg->hp_pins[0]) { |
1241 | return; | 1264 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
1265 | return; | ||
1266 | } | ||
1242 | 1267 | ||
1243 | if (!spec->autocfg.speaker_pins[0]) { | 1268 | if (!cfg->speaker_pins[0]) { |
1244 | if (spec->autocfg.line_out_pins[0] && | 1269 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) |
1245 | spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
1246 | spec->autocfg.speaker_pins[0] = | ||
1247 | spec->autocfg.line_out_pins[0]; | ||
1248 | else | ||
1249 | return; | 1270 | return; |
1271 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
1272 | sizeof(cfg->speaker_pins)); | ||
1273 | cfg->speaker_outs = cfg->line_outs; | ||
1274 | } | ||
1275 | |||
1276 | if (!cfg->hp_pins[0]) { | ||
1277 | memcpy(cfg->hp_pins, cfg->line_out_pins, | ||
1278 | sizeof(cfg->hp_pins)); | ||
1279 | cfg->hp_outs = cfg->line_outs; | ||
1250 | } | 1280 | } |
1251 | 1281 | ||
1252 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 1282 | for (i = 0; i < cfg->hp_outs; i++) { |
1253 | spec->autocfg.hp_pins[0]); | 1283 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", |
1254 | snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0, | 1284 | cfg->hp_pins[i]); |
1285 | snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0, | ||
1255 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1286 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1256 | AC_USRSP_EN | ALC880_HP_EVENT); | 1287 | AC_USRSP_EN | ALC880_HP_EVENT); |
1288 | } | ||
1257 | spec->unsol_event = alc_sku_unsol_event; | 1289 | spec->unsol_event = alc_sku_unsol_event; |
1258 | } | 1290 | } |
1259 | 1291 | ||
@@ -1711,31 +1743,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { | |||
1711 | 1743 | ||
1712 | static void alc_automute_amp(struct hda_codec *codec) | 1744 | static void alc_automute_amp(struct hda_codec *codec) |
1713 | { | 1745 | { |
1714 | struct alc_spec *spec = codec->spec; | 1746 | alc_automute_speaker(codec, 0); |
1715 | unsigned int mute; | ||
1716 | hda_nid_t nid; | ||
1717 | int i; | ||
1718 | |||
1719 | spec->jack_present = 0; | ||
1720 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { | ||
1721 | nid = spec->autocfg.hp_pins[i]; | ||
1722 | if (!nid) | ||
1723 | break; | ||
1724 | if (snd_hda_jack_detect(codec, nid)) { | ||
1725 | spec->jack_present = 1; | ||
1726 | break; | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1731 | /* Toggle internal speakers muting */ | ||
1732 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | ||
1733 | nid = spec->autocfg.speaker_pins[i]; | ||
1734 | if (!nid) | ||
1735 | break; | ||
1736 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1737 | HDA_AMP_MUTE, mute); | ||
1738 | } | ||
1739 | } | 1747 | } |
1740 | 1748 | ||
1741 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, | 1749 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, |