diff options
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r-- | sound/pci/hda/patch_analog.c | 86 |
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 { hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; unsigned int jack_present :1; - unsigned int inv_jack_detect:1; + unsigned int inv_jack_detect:1; /* inverted jack-detection */ + unsigned int inv_eapd:1; /* inverted EAPD implementation */ #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; @@ -156,15 +157,19 @@ static const char *ad_slave_sws[] = { static void ad198x_free_kctls(struct hda_codec *codec); +#ifdef CONFIG_SND_HDA_INPUT_BEEP /* additional beep mixers; the actual parameters are overwritten at build */ static struct snd_kcontrol_new ad_beep_mixer[] = { HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), + HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT), { } /* end */ }; #define set_beep_amp(spec, nid, idx, dir) \ ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ +#else +#define set_beep_amp(spec, nid, idx, dir) /* NOP */ +#endif static int ad198x_build_controls(struct hda_codec *codec) { @@ -194,6 +199,7 @@ static int ad198x_build_controls(struct hda_codec *codec) } /* create beep controls if needed */ +#ifdef CONFIG_SND_HDA_INPUT_BEEP if (spec->beep_amp) { struct snd_kcontrol_new *knew; for (knew = ad_beep_mixer; knew->name; knew++) { @@ -202,11 +208,14 @@ static int ad198x_build_controls(struct hda_codec *codec) if (!kctl) return -ENOMEM; kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, + get_amp_nid_(spec->beep_amp), + kctl); if (err < 0) return err; } } +#endif /* if we have no master control, let's create it */ if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { @@ -450,7 +459,7 @@ static struct hda_codec_ops ad198x_patch_ops = { /* * EAPD control - * the private value = nid | (invert << 8) + * the private value = nid */ #define ad198x_eapd_info snd_ctl_boolean_mono_info @@ -459,8 +468,7 @@ static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; - int invert = (kcontrol->private_value >> 8) & 1; - if (invert) + if (spec->inv_eapd) ucontrol->value.integer.value[0] = ! spec->cur_eapd; else ucontrol->value.integer.value[0] = spec->cur_eapd; @@ -472,11 +480,10 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; - int invert = (kcontrol->private_value >> 8) & 1; hda_nid_t nid = kcontrol->private_value & 0xff; unsigned int eapd; eapd = !!ucontrol->value.integer.value[0]; - if (invert) + if (spec->inv_eapd) eapd = !eapd; if (eapd == spec->cur_eapd) return 0; @@ -697,7 +704,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { .info = ad198x_eapd_info, .get = ad198x_eapd_get, .put = ad198x_eapd_put, - .private_value = 0x1b | (1 << 8), /* port-D, inversed */ + .private_value = 0x1b, /* port-D */ }, { } /* end */ }; @@ -712,10 +719,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { static void ad1986a_automic(struct hda_codec *codec) { unsigned int present; - present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); + present = snd_hda_jack_detect(codec, 0x1f); /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, - (present & AC_PINSENSE_PRESENCE) ? 0 : 2); + present ? 0 : 2); } #define AD1986A_MIC_EVENT 0x36 @@ -754,10 +761,8 @@ static void ad1986a_update_hp(struct hda_codec *codec) static void ad1986a_hp_automute(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; - unsigned int present; - present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); - spec->jack_present = !!(present & 0x80000000); + spec->jack_present = snd_hda_jack_detect(codec, 0x1a); if (spec->inv_jack_detect) spec->jack_present = !spec->jack_present; ad1986a_update_hp(codec); @@ -1068,6 +1073,7 @@ static int patch_ad1986a(struct hda_codec *codec) spec->loopback.amplist = ad1986a_loopbacks; #endif spec->vmaster_nid = 0x1b; + spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */ codec->patch_ops = ad198x_patch_ops; @@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec) { unsigned int present; - present = snd_hda_codec_read(codec, 0x06, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + present = snd_hda_jack_detect(codec, 0x06); snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); } @@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec) }; unsigned int present; - present = snd_hda_codec_read(codec, 0x08, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + present = snd_hda_jack_detect(codec, 0x08); if (present) snd_hda_sequence_write(codec, mic_jack_on); else @@ -1785,6 +1789,14 @@ static int patch_ad1981(struct hda_codec *codec) codec->patch_ops.init = ad1981_hp_init; codec->patch_ops.unsol_event = ad1981_hp_unsol_event; + /* set the upper-limit for mixer amp to 0dB for avoiding the + * possible damage by overloading + */ + snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); break; case AD1981_THINKPAD: spec->mixers[0] = ad1981_thinkpad_mixers; @@ -2120,7 +2132,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { .info = ad198x_eapd_info, .get = ad198x_eapd_get, .put = ad198x_eapd_put, - .private_value = 0x12 | (1 << 8), /* port-D, inversed */ + .private_value = 0x12, /* port-D */ }, { } /* end */ @@ -2524,7 +2536,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) { if ((res >> 26) != AD1988_HP_EVENT) return; - if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31)) + if (snd_hda_jack_detect(codec, 0x11)) snd_hda_sequence_write(codec, ad1988_laptop_hp_on); else 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, knew->name = kstrdup(name, GFP_KERNEL); if (! knew->name) return -ENOMEM; + if (get_amp_nid_(val)) + knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); knew->private_value = val; return 0; } @@ -3059,6 +3073,7 @@ static int patch_ad1988(struct hda_codec *codec) spec->input_mux = &ad1988_laptop_capture_source; spec->num_mixers = 1; spec->mixers[0] = ad1988_laptop_mixers; + spec->inv_eapd = 1; /* inverted EAPD */ spec->num_init_verbs = 1; spec->init_verbs[0] = ad1988_laptop_init_verbs; if (board_config == AD1988_LAPTOP_DIG) @@ -3768,8 +3783,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec) { unsigned int present; - present = snd_hda_codec_read(codec, 0x11, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + present = snd_hda_jack_detect(codec, 0x11); snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 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) { unsigned int present; - present = snd_hda_codec_read(codec, 0x14, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + present = snd_hda_jack_detect(codec, 0x14); snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, present ? 0 : 1); } @@ -3817,13 +3830,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec) { unsigned int present; - present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0); - present &= AC_PINSENSE_PRESENCE; - if (!present) { - present = snd_hda_codec_read(codec, 0x12, 0, - AC_VERB_GET_PIN_SENSE, 0); - present &= AC_PINSENSE_PRESENCE; - } + present = snd_hda_jack_detect(codec, 0x11); + if (!present) + present = snd_hda_jack_detect(codec, 0x12); snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 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) { unsigned int idx; - if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & - AC_PINSENSE_PRESENCE) + if (snd_hda_jack_detect(codec, 0x14)) idx = 0; - else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & - AC_PINSENSE_PRESENCE) + else if (snd_hda_jack_detect(codec, 0x1c)) idx = 4; else idx = 1; @@ -4008,8 +4015,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec) { unsigned int present; - present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) - & AC_PINSENSE_PRESENCE; + present = snd_hda_jack_detect(codec, 0x11); snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); } @@ -4117,14 +4123,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { /* switch to external mic if plugged */ static void ad1984a_touchsmart_automic(struct hda_codec *codec) { - if (snd_hda_codec_read(codec, 0x1c, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { + if (snd_hda_jack_detect(codec, 0x1c)) snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x4); - } else { + else snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x5); - } } |