aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-04-28 08:41:52 -0400
committerTakashi Iwai <tiwai@suse.de>2011-04-28 08:45:56 -0400
commite6a5e1b7094bdd5cc9ae969aff7f75fbc53517fc (patch)
tree7703778eb6f7bbc1aed6e38284c8c3ab132ac195 /sound/pci/hda/patch_realtek.c
parent3b8510ce972c93000ea65122bab3a278074eda98 (diff)
ALSA: hda - Add support of line-out automute for Realtek
Add the common helper function and flags to support the auto-mute per line-out jack detection, and also the mute of line-out jacks. A few model-specific implementations are replaced with the common helpers. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c274
1 files changed, 120 insertions, 154 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index af9bb96d6849..222abba98168 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -392,9 +392,12 @@ struct alc_spec {
392 /* for pin sensing */ 392 /* for pin sensing */
393 unsigned int sense_updated: 1; 393 unsigned int sense_updated: 1;
394 unsigned int jack_present: 1; 394 unsigned int jack_present: 1;
395 unsigned int line_jack_present:1;
395 unsigned int master_sw: 1; 396 unsigned int master_sw: 1;
396 unsigned int auto_mic:1; 397 unsigned int auto_mic:1;
397 unsigned int automute:1; /* HP automute enabled */ 398 unsigned int automute:1; /* HP automute enabled */
399 unsigned int detect_line:1; /* Line-out detection enabled */
400 unsigned int automute_lines:1; /* automute line-out as well */
398 401
399 /* other flags */ 402 /* other flags */
400 unsigned int no_analog :1; /* digital I/O only */ 403 unsigned int no_analog :1; /* digital I/O only */
@@ -1074,54 +1077,96 @@ static int alc_init_jacks(struct hda_codec *codec)
1074 return 0; 1077 return 0;
1075} 1078}
1076 1079
1077static void alc_hp_automute(struct hda_codec *codec) 1080static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
1078{ 1081{
1079 struct alc_spec *spec = codec->spec; 1082 int i, present = 0;
1080 unsigned int mute;
1081 hda_nid_t nid;
1082 int i;
1083 1083
1084 if (!spec->automute) 1084 for (i = 0; i < num_pins; i++) {
1085 return; 1085 hda_nid_t nid = pins[i];
1086
1087 spec->jack_present = 0;
1088 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1089 nid = spec->autocfg.hp_pins[i];
1090 if (!nid) 1086 if (!nid)
1091 break; 1087 break;
1092 snd_hda_input_jack_report(codec, nid); 1088 snd_hda_input_jack_report(codec, nid);
1093 spec->jack_present |= snd_hda_jack_detect(codec, nid); 1089 present |= snd_hda_jack_detect(codec, nid);
1094 } 1090 }
1091 return present;
1092}
1095 1093
1096 mute = spec->jack_present ? HDA_AMP_MUTE : 0; 1094static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
1097 /* Toggle internal speakers muting */ 1095 bool mute)
1098 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { 1096{
1099 nid = spec->autocfg.speaker_pins[i]; 1097 struct alc_spec *spec = codec->spec;
1098 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
1099 unsigned int pin_bits = mute ? 0 : PIN_OUT;
1100 int i;
1101
1102 for (i = 0; i < num_pins; i++) {
1103 hda_nid_t nid = pins[i];
1100 if (!nid) 1104 if (!nid)
1101 break; 1105 break;
1102 switch (spec->automute_mode) { 1106 switch (spec->automute_mode) {
1103 case ALC_AUTOMUTE_PIN: 1107 case ALC_AUTOMUTE_PIN:
1104 snd_hda_codec_write(codec, nid, 0, 1108 snd_hda_codec_write(codec, nid, 0,
1105 AC_VERB_SET_PIN_WIDGET_CONTROL, 1109 AC_VERB_SET_PIN_WIDGET_CONTROL,
1106 spec->jack_present ? 0 : PIN_OUT); 1110 pin_bits);
1107 break; 1111 break;
1108 case ALC_AUTOMUTE_AMP: 1112 case ALC_AUTOMUTE_AMP:
1109 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 1113 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1110 HDA_AMP_MUTE, mute); 1114 HDA_AMP_MUTE, mute_bits);
1111 break; 1115 break;
1112 case ALC_AUTOMUTE_MIXER: 1116 case ALC_AUTOMUTE_MIXER:
1113 nid = spec->automute_mixer_nid[i]; 1117 nid = spec->automute_mixer_nid[i];
1114 if (!nid) 1118 if (!nid)
1115 break; 1119 break;
1116 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, 1120 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
1117 HDA_AMP_MUTE, mute); 1121 HDA_AMP_MUTE, mute_bits);
1118 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1, 1122 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
1119 HDA_AMP_MUTE, mute); 1123 HDA_AMP_MUTE, mute_bits);
1120 break; 1124 break;
1121 } 1125 }
1122 } 1126 }
1123} 1127}
1124 1128
1129/* Toggle internal speakers muting */
1130static void update_speakers(struct hda_codec *codec)
1131{
1132 struct alc_spec *spec = codec->spec;
1133
1134 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
1135 spec->autocfg.speaker_pins,
1136 spec->jack_present | spec->line_jack_present);
1137
1138 /* toggle line-out mutes if needed, too */
1139 if (!spec->automute_lines)
1140 return;
1141 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1142 spec->autocfg.line_out_pins,
1143 spec->jack_present);
1144}
1145
1146static void alc_hp_automute(struct hda_codec *codec)
1147{
1148 struct alc_spec *spec = codec->spec;
1149
1150 if (!spec->automute)
1151 return;
1152 spec->jack_present =
1153 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
1154 spec->autocfg.hp_pins);
1155 update_speakers(codec);
1156}
1157
1158static void alc_line_automute(struct hda_codec *codec)
1159{
1160 struct alc_spec *spec = codec->spec;
1161
1162 if (!spec->automute || !spec->detect_line)
1163 return;
1164 spec->line_jack_present =
1165 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
1166 spec->autocfg.line_out_pins);
1167 update_speakers(codec);
1168}
1169
1125static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, 1170static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1126 hda_nid_t nid) 1171 hda_nid_t nid)
1127{ 1172{
@@ -1219,6 +1264,9 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1219 case ALC880_HP_EVENT: 1264 case ALC880_HP_EVENT:
1220 alc_hp_automute(codec); 1265 alc_hp_automute(codec);
1221 break; 1266 break;
1267 case ALC880_FRONT_EVENT:
1268 alc_line_automute(codec);
1269 break;
1222 case ALC880_MIC_EVENT: 1270 case ALC880_MIC_EVENT:
1223 alc_mic_automute(codec); 1271 alc_mic_automute(codec);
1224 break; 1272 break;
@@ -1228,6 +1276,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1228static void alc_inithook(struct hda_codec *codec) 1276static void alc_inithook(struct hda_codec *codec)
1229{ 1277{
1230 alc_hp_automute(codec); 1278 alc_hp_automute(codec);
1279 alc_line_automute(codec);
1231 alc_mic_automute(codec); 1280 alc_mic_automute(codec);
1232} 1281}
1233 1282
@@ -9551,33 +9600,15 @@ static struct hda_channel_mode alc888_3st_hp_modes[3] = {
9551 { 6, alc888_3st_hp_6ch_init }, 9600 { 6, alc888_3st_hp_6ch_init },
9552}; 9601};
9553 9602
9554/* toggle front-jack and RCA according to the hp-jack state */ 9603static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
9555static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
9556{
9557 unsigned int present = snd_hda_jack_detect(codec, 0x1b);
9558
9559 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9560 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9561 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9562 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9563}
9564
9565/* toggle RCA according to the front-jack state */
9566static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
9567{ 9604{
9568 unsigned int present = snd_hda_jack_detect(codec, 0x14); 9605 struct alc_spec *spec = codec->spec;
9569
9570 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9571 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9572}
9573 9606
9574static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, 9607 spec->autocfg.hp_pins[0] = 0x1b;
9575 unsigned int res) 9608 spec->autocfg.line_out_pins[0] = 0x14;
9576{ 9609 spec->autocfg.speaker_pins[0] = 0x15;
9577 if ((res >> 26) == ALC880_HP_EVENT) 9610 spec->automute = 1;
9578 alc888_lenovo_ms7195_front_automute(codec); 9611 spec->automute_mode = ALC_AUTOMUTE_AMP;
9579 if ((res >> 26) == ALC880_FRONT_EVENT)
9580 alc888_lenovo_ms7195_rca_automute(codec);
9581} 9612}
9582 9613
9583/* toggle speaker-output according to the hp-jack state */ 9614/* toggle speaker-output according to the hp-jack state */
@@ -9645,31 +9676,17 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
9645 spec->automute_mode = ALC_AUTOMUTE_AMP; 9676 spec->automute_mode = ALC_AUTOMUTE_AMP;
9646} 9677}
9647 9678
9648static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 9679static void alc883_lenovo_101e_setup(struct hda_codec *codec)
9649{ 9680{
9650 int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0; 9681 struct alc_spec *spec = codec->spec;
9651
9652 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9653 HDA_AMP_MUTE, bits);
9654}
9655
9656static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
9657{
9658 int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
9659
9660 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9661 HDA_AMP_MUTE, bits);
9662 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9663 HDA_AMP_MUTE, bits);
9664}
9665 9682
9666static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, 9683 spec->autocfg.hp_pins[0] = 0x1b;
9667 unsigned int res) 9684 spec->autocfg.line_out_pins[0] = 0x14;
9668{ 9685 spec->autocfg.speaker_pins[0] = 0x15;
9669 if ((res >> 26) == ALC880_HP_EVENT) 9686 spec->automute = 1;
9670 alc883_lenovo_101e_all_automute(codec); 9687 spec->detect_line = 1;
9671 if ((res >> 26) == ALC880_FRONT_EVENT) 9688 spec->automute_lines = 1;
9672 alc883_lenovo_101e_ispeaker_automute(codec); 9689 spec->automute_mode = ALC_AUTOMUTE_AMP;
9673} 9690}
9674 9691
9675/* toggle speaker-output according to the hp-jack state */ 9692/* toggle speaker-output according to the hp-jack state */
@@ -10584,8 +10601,9 @@ static struct alc_config_preset alc882_presets[] = {
10584 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), 10601 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10585 .channel_mode = alc883_3ST_2ch_modes, 10602 .channel_mode = alc883_3ST_2ch_modes,
10586 .input_mux = &alc883_lenovo_101e_capture_source, 10603 .input_mux = &alc883_lenovo_101e_capture_source,
10587 .unsol_event = alc883_lenovo_101e_unsol_event, 10604 .setup = alc883_lenovo_101e_setup,
10588 .init_hook = alc883_lenovo_101e_all_automute, 10605 .unsol_event = alc_sku_unsol_event,
10606 .init_hook = alc_inithook,
10589 }, 10607 },
10590 [ALC883_LENOVO_NB0763] = { 10608 [ALC883_LENOVO_NB0763] = {
10591 .mixers = { alc883_lenovo_nb0763_mixer }, 10609 .mixers = { alc883_lenovo_nb0763_mixer },
@@ -10610,8 +10628,9 @@ static struct alc_config_preset alc882_presets[] = {
10610 .channel_mode = alc883_3ST_6ch_modes, 10628 .channel_mode = alc883_3ST_6ch_modes,
10611 .need_dac_fix = 1, 10629 .need_dac_fix = 1,
10612 .input_mux = &alc883_capture_source, 10630 .input_mux = &alc883_capture_source,
10613 .unsol_event = alc883_lenovo_ms7195_unsol_event, 10631 .unsol_event = alc_sku_unsol_event,
10614 .init_hook = alc888_lenovo_ms7195_front_automute, 10632 .setup = alc888_lenovo_ms7195_setup,
10633 .init_hook = alc_inithook,
10615 }, 10634 },
10616 [ALC883_HAIER_W66] = { 10635 [ALC883_HAIER_W66] = {
10617 .mixers = { alc883_targa_2ch_mixer}, 10636 .mixers = { alc883_targa_2ch_mixer},
@@ -18217,39 +18236,17 @@ static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
18217 { } /* end */ 18236 { } /* end */
18218}; 18237};
18219 18238
18220static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) 18239static void alc662_lenovo_101e_setup(struct hda_codec *codec)
18221{ 18240{
18222 unsigned int present; 18241 struct alc_spec *spec = codec->spec;
18223 unsigned char bits;
18224
18225 present = snd_hda_jack_detect(codec, 0x14);
18226 bits = present ? HDA_AMP_MUTE : 0;
18227
18228 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
18229 HDA_AMP_MUTE, bits);
18230}
18231
18232static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
18233{
18234 unsigned int present;
18235 unsigned char bits;
18236
18237 present = snd_hda_jack_detect(codec, 0x1b);
18238 bits = present ? HDA_AMP_MUTE : 0;
18239
18240 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
18241 HDA_AMP_MUTE, bits);
18242 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
18243 HDA_AMP_MUTE, bits);
18244}
18245 18242
18246static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, 18243 spec->autocfg.hp_pins[0] = 0x1b;
18247 unsigned int res) 18244 spec->autocfg.line_out_pins[0] = 0x14;
18248{ 18245 spec->autocfg.speaker_pins[0] = 0x15;
18249 if ((res >> 26) == ALC880_HP_EVENT) 18246 spec->automute = 1;
18250 alc662_lenovo_101e_all_automute(codec); 18247 spec->detect_line = 1;
18251 if ((res >> 26) == ALC880_FRONT_EVENT) 18248 spec->automute_lines = 1;
18252 alc662_lenovo_101e_ispeaker_automute(codec); 18249 spec->automute_mode = ALC_AUTOMUTE_AMP;
18253} 18250}
18254 18251
18255/* unsolicited event for HP jack sensing */ 18252/* unsolicited event for HP jack sensing */
@@ -18439,53 +18436,21 @@ static void alc663_mode8_setup(struct hda_codec *codec)
18439 spec->auto_mic = 1; 18436 spec->auto_mic = 1;
18440} 18437}
18441 18438
18442static void alc663_g71v_hp_automute(struct hda_codec *codec) 18439static void alc663_g71v_setup(struct hda_codec *codec)
18443{
18444 unsigned int present;
18445 unsigned char bits;
18446
18447 present = snd_hda_jack_detect(codec, 0x21);
18448 bits = present ? HDA_AMP_MUTE : 0;
18449 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
18450 HDA_AMP_MUTE, bits);
18451 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
18452 HDA_AMP_MUTE, bits);
18453}
18454
18455static void alc663_g71v_front_automute(struct hda_codec *codec)
18456{ 18440{
18457 unsigned int present; 18441 struct alc_spec *spec = codec->spec;
18458 unsigned char bits; 18442 spec->autocfg.hp_pins[0] = 0x21;
18459 18443 spec->autocfg.line_out_pins[0] = 0x15;
18460 present = snd_hda_jack_detect(codec, 0x15); 18444 spec->autocfg.speaker_pins[0] = 0x14;
18461 bits = present ? HDA_AMP_MUTE : 0; 18445 spec->automute = 1;
18462 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, 18446 spec->automute_mode = ALC_AUTOMUTE_AMP;
18463 HDA_AMP_MUTE, bits); 18447 spec->detect_line = 1;
18464} 18448 spec->automute_lines = 1;
18465 18449 spec->ext_mic.pin = 0x18;
18466static void alc663_g71v_unsol_event(struct hda_codec *codec, 18450 spec->ext_mic.mux_idx = 0;
18467 unsigned int res) 18451 spec->int_mic.pin = 0x12;
18468{ 18452 spec->int_mic.mux_idx = 9;
18469 switch (res >> 26) { 18453 spec->auto_mic = 1;
18470 case ALC880_HP_EVENT:
18471 alc663_g71v_hp_automute(codec);
18472 break;
18473 case ALC880_FRONT_EVENT:
18474 alc663_g71v_front_automute(codec);
18475 break;
18476 case ALC880_MIC_EVENT:
18477 alc_mic_automute(codec);
18478 break;
18479 }
18480}
18481
18482#define alc663_g71v_setup alc663_m51va_setup
18483
18484static void alc663_g71v_inithook(struct hda_codec *codec)
18485{
18486 alc663_g71v_front_automute(codec);
18487 alc663_g71v_hp_automute(codec);
18488 alc_mic_automute(codec);
18489} 18454}
18490 18455
18491#define alc663_g50v_setup alc663_m51va_setup 18456#define alc663_g50v_setup alc663_m51va_setup
@@ -18697,8 +18662,9 @@ static struct alc_config_preset alc662_presets[] = {
18697 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 18662 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18698 .channel_mode = alc662_3ST_2ch_modes, 18663 .channel_mode = alc662_3ST_2ch_modes,
18699 .input_mux = &alc662_lenovo_101e_capture_source, 18664 .input_mux = &alc662_lenovo_101e_capture_source,
18700 .unsol_event = alc662_lenovo_101e_unsol_event, 18665 .unsol_event = alc_sku_unsol_event,
18701 .init_hook = alc662_lenovo_101e_all_automute, 18666 .setup = alc662_lenovo_101e_setup,
18667 .init_hook = alc_inithook,
18702 }, 18668 },
18703 [ALC662_ASUS_EEEPC_P701] = { 18669 [ALC662_ASUS_EEEPC_P701] = {
18704 .mixers = { alc662_eeepc_p701_mixer }, 18670 .mixers = { alc662_eeepc_p701_mixer },
@@ -18765,9 +18731,9 @@ static struct alc_config_preset alc662_presets[] = {
18765 .dig_out_nid = ALC662_DIGOUT_NID, 18731 .dig_out_nid = ALC662_DIGOUT_NID,
18766 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), 18732 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18767 .channel_mode = alc662_3ST_2ch_modes, 18733 .channel_mode = alc662_3ST_2ch_modes,
18768 .unsol_event = alc663_g71v_unsol_event, 18734 .unsol_event = alc_sku_unsol_event,
18769 .setup = alc663_g71v_setup, 18735 .setup = alc663_g71v_setup,
18770 .init_hook = alc663_g71v_inithook, 18736 .init_hook = alc_inithook,
18771 }, 18737 },
18772 [ALC663_ASUS_H13] = { 18738 [ALC663_ASUS_H13] = {
18773 .mixers = { alc663_m51va_mixer }, 18739 .mixers = { alc663_m51va_mixer },