aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c86
1 files changed, 45 insertions, 41 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2d603f6aba63..1a36137e13ec 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -72,7 +72,8 @@ struct ad198x_spec {
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
73 73
74 unsigned int jack_present :1; 74 unsigned int jack_present :1;
75 unsigned int inv_jack_detect:1; 75 unsigned int inv_jack_detect:1; /* inverted jack-detection */
76 unsigned int inv_eapd:1; /* inverted EAPD implementation */
76 77
77#ifdef CONFIG_SND_HDA_POWER_SAVE 78#ifdef CONFIG_SND_HDA_POWER_SAVE
78 struct hda_loopback_check loopback; 79 struct hda_loopback_check loopback;
@@ -156,15 +157,19 @@ static const char *ad_slave_sws[] = {
156 157
157static void ad198x_free_kctls(struct hda_codec *codec); 158static void ad198x_free_kctls(struct hda_codec *codec);
158 159
160#ifdef CONFIG_SND_HDA_INPUT_BEEP
159/* additional beep mixers; the actual parameters are overwritten at build */ 161/* additional beep mixers; the actual parameters are overwritten at build */
160static struct snd_kcontrol_new ad_beep_mixer[] = { 162static struct snd_kcontrol_new ad_beep_mixer[] = {
161 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), 163 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
162 HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), 164 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
163 { } /* end */ 165 { } /* end */
164}; 166};
165 167
166#define set_beep_amp(spec, nid, idx, dir) \ 168#define set_beep_amp(spec, nid, idx, dir) \
167 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ 169 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
170#else
171#define set_beep_amp(spec, nid, idx, dir) /* NOP */
172#endif
168 173
169static int ad198x_build_controls(struct hda_codec *codec) 174static int ad198x_build_controls(struct hda_codec *codec)
170{ 175{
@@ -194,6 +199,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
194 } 199 }
195 200
196 /* create beep controls if needed */ 201 /* create beep controls if needed */
202#ifdef CONFIG_SND_HDA_INPUT_BEEP
197 if (spec->beep_amp) { 203 if (spec->beep_amp) {
198 struct snd_kcontrol_new *knew; 204 struct snd_kcontrol_new *knew;
199 for (knew = ad_beep_mixer; knew->name; knew++) { 205 for (knew = ad_beep_mixer; knew->name; knew++) {
@@ -202,11 +208,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
202 if (!kctl) 208 if (!kctl)
203 return -ENOMEM; 209 return -ENOMEM;
204 kctl->private_value = spec->beep_amp; 210 kctl->private_value = spec->beep_amp;
205 err = snd_hda_ctl_add(codec, kctl); 211 err = snd_hda_ctl_add(codec,
212 get_amp_nid_(spec->beep_amp),
213 kctl);
206 if (err < 0) 214 if (err < 0)
207 return err; 215 return err;
208 } 216 }
209 } 217 }
218#endif
210 219
211 /* if we have no master control, let's create it */ 220 /* if we have no master control, let's create it */
212 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 221 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
@@ -450,7 +459,7 @@ static struct hda_codec_ops ad198x_patch_ops = {
450 459
451/* 460/*
452 * EAPD control 461 * EAPD control
453 * the private value = nid | (invert << 8) 462 * the private value = nid
454 */ 463 */
455#define ad198x_eapd_info snd_ctl_boolean_mono_info 464#define ad198x_eapd_info snd_ctl_boolean_mono_info
456 465
@@ -459,8 +468,7 @@ static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
459{ 468{
460 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 469 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
461 struct ad198x_spec *spec = codec->spec; 470 struct ad198x_spec *spec = codec->spec;
462 int invert = (kcontrol->private_value >> 8) & 1; 471 if (spec->inv_eapd)
463 if (invert)
464 ucontrol->value.integer.value[0] = ! spec->cur_eapd; 472 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
465 else 473 else
466 ucontrol->value.integer.value[0] = spec->cur_eapd; 474 ucontrol->value.integer.value[0] = spec->cur_eapd;
@@ -472,11 +480,10 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
472{ 480{
473 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 481 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
474 struct ad198x_spec *spec = codec->spec; 482 struct ad198x_spec *spec = codec->spec;
475 int invert = (kcontrol->private_value >> 8) & 1;
476 hda_nid_t nid = kcontrol->private_value & 0xff; 483 hda_nid_t nid = kcontrol->private_value & 0xff;
477 unsigned int eapd; 484 unsigned int eapd;
478 eapd = !!ucontrol->value.integer.value[0]; 485 eapd = !!ucontrol->value.integer.value[0];
479 if (invert) 486 if (spec->inv_eapd)
480 eapd = !eapd; 487 eapd = !eapd;
481 if (eapd == spec->cur_eapd) 488 if (eapd == spec->cur_eapd)
482 return 0; 489 return 0;
@@ -697,7 +704,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
697 .info = ad198x_eapd_info, 704 .info = ad198x_eapd_info,
698 .get = ad198x_eapd_get, 705 .get = ad198x_eapd_get,
699 .put = ad198x_eapd_put, 706 .put = ad198x_eapd_put,
700 .private_value = 0x1b | (1 << 8), /* port-D, inversed */ 707 .private_value = 0x1b, /* port-D */
701 }, 708 },
702 { } /* end */ 709 { } /* end */
703}; 710};
@@ -712,10 +719,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
712static void ad1986a_automic(struct hda_codec *codec) 719static void ad1986a_automic(struct hda_codec *codec)
713{ 720{
714 unsigned int present; 721 unsigned int present;
715 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); 722 present = snd_hda_jack_detect(codec, 0x1f);
716 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ 723 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
717 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, 724 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
718 (present & AC_PINSENSE_PRESENCE) ? 0 : 2); 725 present ? 0 : 2);
719} 726}
720 727
721#define AD1986A_MIC_EVENT 0x36 728#define AD1986A_MIC_EVENT 0x36
@@ -754,10 +761,8 @@ static void ad1986a_update_hp(struct hda_codec *codec)
754static void ad1986a_hp_automute(struct hda_codec *codec) 761static void ad1986a_hp_automute(struct hda_codec *codec)
755{ 762{
756 struct ad198x_spec *spec = codec->spec; 763 struct ad198x_spec *spec = codec->spec;
757 unsigned int present;
758 764
759 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); 765 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
760 spec->jack_present = !!(present & 0x80000000);
761 if (spec->inv_jack_detect) 766 if (spec->inv_jack_detect)
762 spec->jack_present = !spec->jack_present; 767 spec->jack_present = !spec->jack_present;
763 ad1986a_update_hp(codec); 768 ad1986a_update_hp(codec);
@@ -1068,6 +1073,7 @@ static int patch_ad1986a(struct hda_codec *codec)
1068 spec->loopback.amplist = ad1986a_loopbacks; 1073 spec->loopback.amplist = ad1986a_loopbacks;
1069#endif 1074#endif
1070 spec->vmaster_nid = 0x1b; 1075 spec->vmaster_nid = 0x1b;
1076 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1071 1077
1072 codec->patch_ops = ad198x_patch_ops; 1078 codec->patch_ops = ad198x_patch_ops;
1073 1079
@@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec)
1547{ 1553{
1548 unsigned int present; 1554 unsigned int present;
1549 1555
1550 present = snd_hda_codec_read(codec, 0x06, 0, 1556 present = snd_hda_jack_detect(codec, 0x06);
1551 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1552 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, 1557 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1553 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 1558 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1554} 1559}
@@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec)
1568 }; 1573 };
1569 unsigned int present; 1574 unsigned int present;
1570 1575
1571 present = snd_hda_codec_read(codec, 0x08, 0, 1576 present = snd_hda_jack_detect(codec, 0x08);
1572 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1573 if (present) 1577 if (present)
1574 snd_hda_sequence_write(codec, mic_jack_on); 1578 snd_hda_sequence_write(codec, mic_jack_on);
1575 else 1579 else
@@ -1785,6 +1789,14 @@ static int patch_ad1981(struct hda_codec *codec)
1785 1789
1786 codec->patch_ops.init = ad1981_hp_init; 1790 codec->patch_ops.init = ad1981_hp_init;
1787 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 1791 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1792 /* set the upper-limit for mixer amp to 0dB for avoiding the
1793 * possible damage by overloading
1794 */
1795 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1796 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1797 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1798 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1799 (1 << AC_AMPCAP_MUTE_SHIFT));
1788 break; 1800 break;
1789 case AD1981_THINKPAD: 1801 case AD1981_THINKPAD:
1790 spec->mixers[0] = ad1981_thinkpad_mixers; 1802 spec->mixers[0] = ad1981_thinkpad_mixers;
@@ -2120,7 +2132,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2120 .info = ad198x_eapd_info, 2132 .info = ad198x_eapd_info,
2121 .get = ad198x_eapd_get, 2133 .get = ad198x_eapd_get,
2122 .put = ad198x_eapd_put, 2134 .put = ad198x_eapd_put,
2123 .private_value = 0x12 | (1 << 8), /* port-D, inversed */ 2135 .private_value = 0x12, /* port-D */
2124 }, 2136 },
2125 2137
2126 { } /* end */ 2138 { } /* end */
@@ -2524,7 +2536,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2524{ 2536{
2525 if ((res >> 26) != AD1988_HP_EVENT) 2537 if ((res >> 26) != AD1988_HP_EVENT)
2526 return; 2538 return;
2527 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31)) 2539 if (snd_hda_jack_detect(codec, 0x11))
2528 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 2540 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2529 else 2541 else
2530 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 2542 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
@@ -2569,6 +2581,8 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
2569 knew->name = kstrdup(name, GFP_KERNEL); 2581 knew->name = kstrdup(name, GFP_KERNEL);
2570 if (! knew->name) 2582 if (! knew->name)
2571 return -ENOMEM; 2583 return -ENOMEM;
2584 if (get_amp_nid_(val))
2585 knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
2572 knew->private_value = val; 2586 knew->private_value = val;
2573 return 0; 2587 return 0;
2574} 2588}
@@ -3059,6 +3073,7 @@ static int patch_ad1988(struct hda_codec *codec)
3059 spec->input_mux = &ad1988_laptop_capture_source; 3073 spec->input_mux = &ad1988_laptop_capture_source;
3060 spec->num_mixers = 1; 3074 spec->num_mixers = 1;
3061 spec->mixers[0] = ad1988_laptop_mixers; 3075 spec->mixers[0] = ad1988_laptop_mixers;
3076 spec->inv_eapd = 1; /* inverted EAPD */
3062 spec->num_init_verbs = 1; 3077 spec->num_init_verbs = 1;
3063 spec->init_verbs[0] = ad1988_laptop_init_verbs; 3078 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3064 if (board_config == AD1988_LAPTOP_DIG) 3079 if (board_config == AD1988_LAPTOP_DIG)
@@ -3768,8 +3783,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec)
3768{ 3783{
3769 unsigned int present; 3784 unsigned int present;
3770 3785
3771 present = snd_hda_codec_read(codec, 0x11, 0, 3786 present = snd_hda_jack_detect(codec, 0x11);
3772 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3773 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 3787 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3774 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 3788 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3775 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 3789 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
@@ -3781,8 +3795,7 @@ static void ad1884a_hp_automic(struct hda_codec *codec)
3781{ 3795{
3782 unsigned int present; 3796 unsigned int present;
3783 3797
3784 present = snd_hda_codec_read(codec, 0x14, 0, 3798 present = snd_hda_jack_detect(codec, 0x14);
3785 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3786 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 3799 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3787 present ? 0 : 1); 3800 present ? 0 : 1);
3788} 3801}
@@ -3817,13 +3830,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec)
3817{ 3830{
3818 unsigned int present; 3831 unsigned int present;
3819 3832
3820 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0); 3833 present = snd_hda_jack_detect(codec, 0x11);
3821 present &= AC_PINSENSE_PRESENCE; 3834 if (!present)
3822 if (!present) { 3835 present = snd_hda_jack_detect(codec, 0x12);
3823 present = snd_hda_codec_read(codec, 0x12, 0,
3824 AC_VERB_GET_PIN_SENSE, 0);
3825 present &= AC_PINSENSE_PRESENCE;
3826 }
3827 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, 3836 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3828 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 3837 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3829 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, 3838 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
@@ -3835,11 +3844,9 @@ static void ad1884a_laptop_automic(struct hda_codec *codec)
3835{ 3844{
3836 unsigned int idx; 3845 unsigned int idx;
3837 3846
3838 if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & 3847 if (snd_hda_jack_detect(codec, 0x14))
3839 AC_PINSENSE_PRESENCE)
3840 idx = 0; 3848 idx = 0;
3841 else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & 3849 else if (snd_hda_jack_detect(codec, 0x1c))
3842 AC_PINSENSE_PRESENCE)
3843 idx = 4; 3850 idx = 4;
3844 else 3851 else
3845 idx = 1; 3852 idx = 1;
@@ -4008,8 +4015,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4008{ 4015{
4009 unsigned int present; 4016 unsigned int present;
4010 4017
4011 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) 4018 present = snd_hda_jack_detect(codec, 0x11);
4012 & AC_PINSENSE_PRESENCE;
4013 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, 4019 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4014 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 4020 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4015} 4021}
@@ -4117,14 +4123,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4117/* switch to external mic if plugged */ 4123/* switch to external mic if plugged */
4118static void ad1984a_touchsmart_automic(struct hda_codec *codec) 4124static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4119{ 4125{
4120 if (snd_hda_codec_read(codec, 0x1c, 0, 4126 if (snd_hda_jack_detect(codec, 0x1c))
4121 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) {
4122 snd_hda_codec_write(codec, 0x0c, 0, 4127 snd_hda_codec_write(codec, 0x0c, 0,
4123 AC_VERB_SET_CONNECT_SEL, 0x4); 4128 AC_VERB_SET_CONNECT_SEL, 0x4);
4124 } else { 4129 else
4125 snd_hda_codec_write(codec, 0x0c, 0, 4130 snd_hda_codec_write(codec, 0x0c, 0,
4126 AC_VERB_SET_CONNECT_SEL, 0x5); 4131 AC_VERB_SET_CONNECT_SEL, 0x5);
4127 }
4128} 4132}
4129 4133
4130 4134