aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-09-08 09:30:49 -0400
committerTakashi Iwai <tiwai@suse.de>2010-09-08 09:48:29 -0400
commitbb35febd16fe5ac8c30f9116a25210c4f63a5267 (patch)
tree72e476187fb90cdc27767c3b9962c764c54ccf59
parent03642c9a444079aa13f0864383a8f9ca04bfd198 (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.c92
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
993static void alc_automute_pin(struct hda_codec *codec) 993static 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
1028static void alc_automute_pin(struct hda_codec *codec)
1029{
1030 alc_automute_speaker(codec, 1);
1031}
1032
1012static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, 1033static 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)
1236static void alc_init_auto_hp(struct hda_codec *codec) 1257static 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
1712static void alc_automute_amp(struct hda_codec *codec) 1744static 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
1741static void alc_automute_amp_unsol_event(struct hda_codec *codec, 1749static void alc_automute_amp_unsol_event(struct hda_codec *codec,