2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <linux/pci.h>
25 #include <linux/module.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
30 #include "hda_auto_parser.h"
33 #include "hda_generic.h"
35 #define ENABLE_AD_STATIC_QUIRKS
38 struct hda_gen_spec gen;
42 unsigned int cur_smux;
45 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
47 #ifdef ENABLE_AD_STATIC_QUIRKS
48 const struct snd_kcontrol_new *mixers[6];
50 const struct hda_verb *init_verbs[6]; /* initialization verbs
51 * don't forget NULL termination!
53 unsigned int num_init_verbs;
56 struct hda_multi_out multiout; /* playback set-up
57 * max_channels, dacs must be set
58 * dig_out_nid and hp_nid are optional
60 unsigned int cur_eapd;
61 unsigned int need_dac_fix;
64 unsigned int num_adc_nids;
65 const hda_nid_t *adc_nids;
66 hda_nid_t dig_in_nid; /* digital-in NID; optional */
69 const struct hda_input_mux *input_mux;
70 const hda_nid_t *capsrc_nids;
71 unsigned int cur_mux[3];
74 const struct hda_channel_mode *channel_mode;
78 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
80 unsigned int spdif_route;
82 unsigned int jack_present: 1;
83 unsigned int inv_jack_detect: 1;/* inverted jack-detection */
84 unsigned int analog_beep: 1; /* analog beep input present */
85 unsigned int avoid_init_slave_vol:1;
88 struct hda_loopback_check loopback;
90 /* for virtual master */
91 hda_nid_t vmaster_nid;
92 const char * const *slave_vols;
93 const char * const *slave_sws;
94 #endif /* ENABLE_AD_STATIC_QUIRKS */
97 #ifdef ENABLE_AD_STATIC_QUIRKS
99 * input MUX handling (common part)
101 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
103 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
104 struct ad198x_spec *spec = codec->spec;
106 return snd_hda_input_mux_info(spec->input_mux, uinfo);
109 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
111 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
112 struct ad198x_spec *spec = codec->spec;
113 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
115 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
119 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
121 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
122 struct ad198x_spec *spec = codec->spec;
123 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
125 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
126 spec->capsrc_nids[adc_idx],
127 &spec->cur_mux[adc_idx]);
131 * initialization (common callbacks)
133 static int ad198x_init(struct hda_codec *codec)
135 struct ad198x_spec *spec = codec->spec;
138 for (i = 0; i < spec->num_init_verbs; i++)
139 snd_hda_sequence_write(codec, spec->init_verbs[i]);
143 static const char * const ad_slave_pfxs[] = {
144 "Front", "Surround", "Center", "LFE", "Side",
145 "Headphone", "Mono", "Speaker", "IEC958",
149 static const char * const ad1988_6stack_fp_slave_pfxs[] = {
150 "Front", "Surround", "Center", "LFE", "Side", "IEC958",
153 #endif /* ENABLE_AD_STATIC_QUIRKS */
155 #ifdef CONFIG_SND_HDA_INPUT_BEEP
156 /* additional beep mixers; the actual parameters are overwritten at build */
157 static const struct snd_kcontrol_new ad_beep_mixer[] = {
158 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
159 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
163 static const struct snd_kcontrol_new ad_beep2_mixer[] = {
164 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
165 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
169 #define set_beep_amp(spec, nid, idx, dir) \
170 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
172 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
175 #ifdef CONFIG_SND_HDA_INPUT_BEEP
176 static int create_beep_ctls(struct hda_codec *codec)
178 struct ad198x_spec *spec = codec->spec;
179 const struct snd_kcontrol_new *knew;
184 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
185 for ( ; knew->name; knew++) {
187 struct snd_kcontrol *kctl;
188 kctl = snd_ctl_new1(knew, codec);
191 kctl->private_value = spec->beep_amp;
192 err = snd_hda_ctl_add(codec, 0, kctl);
199 #define create_beep_ctls(codec) 0
202 #ifdef ENABLE_AD_STATIC_QUIRKS
203 static int ad198x_build_controls(struct hda_codec *codec)
205 struct ad198x_spec *spec = codec->spec;
206 struct snd_kcontrol *kctl;
210 for (i = 0; i < spec->num_mixers; i++) {
211 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
215 if (spec->multiout.dig_out_nid) {
216 err = snd_hda_create_spdif_out_ctls(codec,
217 spec->multiout.dig_out_nid,
218 spec->multiout.dig_out_nid);
221 err = snd_hda_create_spdif_share_sw(codec,
225 spec->multiout.share_spdif = 1;
227 if (spec->dig_in_nid) {
228 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
233 /* create beep controls if needed */
234 err = create_beep_ctls(codec);
238 /* if we have no master control, let's create it */
239 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
240 unsigned int vmaster_tlv[4];
241 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
242 HDA_OUTPUT, vmaster_tlv);
243 err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
246 spec->slave_vols : ad_slave_pfxs),
248 !spec->avoid_init_slave_vol, NULL);
252 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
253 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
256 spec->slave_sws : ad_slave_pfxs),
262 /* assign Capture Source enums to NID */
263 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
265 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
266 for (i = 0; kctl && i < kctl->count; i++) {
267 err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
272 /* assign IEC958 enums to NID */
273 kctl = snd_hda_find_mixer_ctl(codec,
274 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
276 err = snd_hda_add_nid(codec, kctl, 0,
277 spec->multiout.dig_out_nid);
286 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
288 struct ad198x_spec *spec = codec->spec;
289 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
294 * Analog playback callbacks
296 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
297 struct hda_codec *codec,
298 struct snd_pcm_substream *substream)
300 struct ad198x_spec *spec = codec->spec;
301 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
305 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
306 struct hda_codec *codec,
307 unsigned int stream_tag,
309 struct snd_pcm_substream *substream)
311 struct ad198x_spec *spec = codec->spec;
312 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
316 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
317 struct hda_codec *codec,
318 struct snd_pcm_substream *substream)
320 struct ad198x_spec *spec = codec->spec;
321 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
327 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
328 struct hda_codec *codec,
329 struct snd_pcm_substream *substream)
331 struct ad198x_spec *spec = codec->spec;
332 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
335 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
336 struct hda_codec *codec,
337 struct snd_pcm_substream *substream)
339 struct ad198x_spec *spec = codec->spec;
340 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
343 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
344 struct hda_codec *codec,
345 unsigned int stream_tag,
347 struct snd_pcm_substream *substream)
349 struct ad198x_spec *spec = codec->spec;
350 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
354 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
355 struct hda_codec *codec,
356 struct snd_pcm_substream *substream)
358 struct ad198x_spec *spec = codec->spec;
359 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
365 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
366 struct hda_codec *codec,
367 unsigned int stream_tag,
369 struct snd_pcm_substream *substream)
371 struct ad198x_spec *spec = codec->spec;
372 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
373 stream_tag, 0, format);
377 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
378 struct hda_codec *codec,
379 struct snd_pcm_substream *substream)
381 struct ad198x_spec *spec = codec->spec;
382 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
388 static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
391 .channels_max = 6, /* changed later */
392 .nid = 0, /* fill later */
394 .open = ad198x_playback_pcm_open,
395 .prepare = ad198x_playback_pcm_prepare,
396 .cleanup = ad198x_playback_pcm_cleanup,
400 static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
404 .nid = 0, /* fill later */
406 .prepare = ad198x_capture_pcm_prepare,
407 .cleanup = ad198x_capture_pcm_cleanup
411 static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
415 .nid = 0, /* fill later */
417 .open = ad198x_dig_playback_pcm_open,
418 .close = ad198x_dig_playback_pcm_close,
419 .prepare = ad198x_dig_playback_pcm_prepare,
420 .cleanup = ad198x_dig_playback_pcm_cleanup
424 static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
428 /* NID is set in alc_build_pcms */
431 static int ad198x_build_pcms(struct hda_codec *codec)
433 struct ad198x_spec *spec = codec->spec;
434 struct hda_pcm *info = spec->pcm_rec;
437 codec->pcm_info = info;
439 info->name = "AD198x Analog";
440 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
441 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
442 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
443 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
444 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
445 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
447 if (spec->multiout.dig_out_nid) {
450 codec->spdif_status_reset = 1;
451 info->name = "AD198x Digital";
452 info->pcm_type = HDA_PCM_TYPE_SPDIF;
453 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
454 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
455 if (spec->dig_in_nid) {
456 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
457 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
463 #endif /* ENABLE_AD_STATIC_QUIRKS */
465 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
468 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
469 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
470 !codec->inv_eapd ? 0x00 : 0x02);
471 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
472 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
473 !codec->inv_eapd ? 0x00 : 0x02);
476 static void ad198x_power_eapd(struct hda_codec *codec)
478 /* We currently only handle front, HP */
479 switch (codec->vendor_id) {
492 ad198x_power_eapd_write(codec, 0x12, 0x11);
496 ad198x_power_eapd_write(codec, 0x05, 0x06);
499 ad198x_power_eapd_write(codec, 0x1b, 0x1a);
504 static void ad198x_shutup(struct hda_codec *codec)
506 snd_hda_shutup_pins(codec);
507 ad198x_power_eapd(codec);
510 static void ad198x_free(struct hda_codec *codec)
512 struct ad198x_spec *spec = codec->spec;
517 snd_hda_gen_spec_free(&spec->gen);
519 snd_hda_detach_beep_device(codec);
523 static int ad198x_suspend(struct hda_codec *codec)
525 ad198x_shutup(codec);
530 #ifdef ENABLE_AD_STATIC_QUIRKS
531 static const struct hda_codec_ops ad198x_patch_ops = {
532 .build_controls = ad198x_build_controls,
533 .build_pcms = ad198x_build_pcms,
537 .check_power_status = ad198x_check_power_status,
538 .suspend = ad198x_suspend,
540 .reboot_notify = ad198x_shutup,
546 * the private value = nid
548 #define ad198x_eapd_info snd_ctl_boolean_mono_info
550 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
551 struct snd_ctl_elem_value *ucontrol)
553 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
554 struct ad198x_spec *spec = codec->spec;
556 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
558 ucontrol->value.integer.value[0] = spec->cur_eapd;
562 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
563 struct snd_ctl_elem_value *ucontrol)
565 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
566 struct ad198x_spec *spec = codec->spec;
567 hda_nid_t nid = kcontrol->private_value & 0xff;
569 eapd = !!ucontrol->value.integer.value[0];
572 if (eapd == spec->cur_eapd)
574 spec->cur_eapd = eapd;
575 snd_hda_codec_write_cache(codec, nid,
576 0, AC_VERB_SET_EAPD_BTLENABLE,
581 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
582 struct snd_ctl_elem_info *uinfo);
583 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
584 struct snd_ctl_elem_value *ucontrol);
585 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
586 struct snd_ctl_elem_value *ucontrol);
587 #endif /* ENABLE_AD_STATIC_QUIRKS */
591 * Automatic parse of I/O pins from the BIOS configuration
594 static int ad198x_auto_build_controls(struct hda_codec *codec)
598 err = snd_hda_gen_build_controls(codec);
601 err = create_beep_ctls(codec);
607 static const struct hda_codec_ops ad198x_auto_patch_ops = {
608 .build_controls = ad198x_auto_build_controls,
609 .build_pcms = snd_hda_gen_build_pcms,
610 .init = snd_hda_gen_init,
611 .free = snd_hda_gen_free,
612 .unsol_event = snd_hda_jack_unsol_event,
614 .check_power_status = snd_hda_gen_check_power_status,
615 .suspend = ad198x_suspend,
617 .reboot_notify = ad198x_shutup,
621 static int ad198x_parse_auto_config(struct hda_codec *codec)
623 struct ad198x_spec *spec = codec->spec;
624 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
627 codec->spdif_status_reset = 1;
628 codec->no_trigger_sense = 1;
629 codec->no_sticky_stream = 1;
631 spec->gen.indep_hp = 1;
633 err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
636 err = snd_hda_gen_parse_auto_config(codec, cfg);
640 codec->patch_ops = ad198x_auto_patch_ops;
649 #ifdef ENABLE_AD_STATIC_QUIRKS
650 #define AD1986A_SPDIF_OUT 0x02
651 #define AD1986A_FRONT_DAC 0x03
652 #define AD1986A_SURR_DAC 0x04
653 #define AD1986A_CLFE_DAC 0x05
654 #define AD1986A_ADC 0x06
656 static const hda_nid_t ad1986a_dac_nids[3] = {
657 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
659 static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
660 static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
662 static const struct hda_input_mux ad1986a_capture_source = {
676 static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
677 .ops = &snd_hda_bind_vol,
679 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
680 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
681 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
686 static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
687 .ops = &snd_hda_bind_sw,
689 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
690 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
691 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
699 static const struct snd_kcontrol_new ad1986a_mixers[] = {
701 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
703 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
704 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
705 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
706 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
707 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
708 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
709 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
710 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
711 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
712 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
713 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
714 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
715 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
716 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
717 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
718 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
719 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
720 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
721 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
722 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
723 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
724 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
725 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
726 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
727 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
730 .name = "Capture Source",
731 .info = ad198x_mux_enum_info,
732 .get = ad198x_mux_enum_get,
733 .put = ad198x_mux_enum_put,
735 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
739 /* additional mixers for 3stack mode */
740 static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
743 .name = "Channel Mode",
744 .info = ad198x_ch_mode_info,
745 .get = ad198x_ch_mode_get,
746 .put = ad198x_ch_mode_put,
751 /* laptop model - 2ch only */
752 static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
754 /* master controls both pins 0x1a and 0x1b */
755 static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
756 .ops = &snd_hda_bind_vol,
758 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
759 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
764 static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
765 .ops = &snd_hda_bind_sw,
767 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
768 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
773 static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
774 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
775 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
776 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
777 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
778 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
779 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
780 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
781 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
782 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
783 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
784 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
785 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
786 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
788 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
789 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
790 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
791 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
793 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
794 .name = "Capture Source",
795 .info = ad198x_mux_enum_info,
796 .get = ad198x_mux_enum_get,
797 .put = ad198x_mux_enum_put,
802 /* laptop-eapd model - 2ch only */
804 static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
808 { "Internal Mic", 0x4 },
813 static const struct hda_input_mux ad1986a_automic_capture_source = {
821 static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
822 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
823 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
827 static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
828 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
829 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
830 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
831 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
832 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
833 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
834 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
837 .name = "Capture Source",
838 .info = ad198x_mux_enum_info,
839 .get = ad198x_mux_enum_get,
840 .put = ad198x_mux_enum_put,
843 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
844 .name = "External Amplifier",
845 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
846 .info = ad198x_eapd_info,
847 .get = ad198x_eapd_get,
848 .put = ad198x_eapd_put,
849 .private_value = 0x1b, /* port-D */
854 static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
855 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
856 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
860 /* re-connect the mic boost input according to the jack sensing */
861 static void ad1986a_automic(struct hda_codec *codec)
863 unsigned int present;
864 present = snd_hda_jack_detect(codec, 0x1f);
865 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
866 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
870 #define AD1986A_MIC_EVENT 0x36
872 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
875 if ((res >> 26) != AD1986A_MIC_EVENT)
877 ad1986a_automic(codec);
880 static int ad1986a_automic_init(struct hda_codec *codec)
883 ad1986a_automic(codec);
887 /* laptop-automute - 2ch only */
889 static void ad1986a_update_hp(struct hda_codec *codec)
891 struct ad198x_spec *spec = codec->spec;
894 if (spec->jack_present)
895 mute = HDA_AMP_MUTE; /* mute internal speaker */
897 /* unmute internal speaker if necessary */
898 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
899 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
903 static void ad1986a_hp_automute(struct hda_codec *codec)
905 struct ad198x_spec *spec = codec->spec;
907 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
908 if (spec->inv_jack_detect)
909 spec->jack_present = !spec->jack_present;
910 ad1986a_update_hp(codec);
913 #define AD1986A_HP_EVENT 0x37
915 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
917 if ((res >> 26) != AD1986A_HP_EVENT)
919 ad1986a_hp_automute(codec);
922 static int ad1986a_hp_init(struct hda_codec *codec)
925 ad1986a_hp_automute(codec);
929 /* bind hp and internal speaker mute (with plug check) */
930 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
931 struct snd_ctl_elem_value *ucontrol)
933 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
934 int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
936 ad1986a_update_hp(codec);
940 static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
941 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
944 .name = "Master Playback Switch",
945 .subdevice = HDA_SUBDEV_AMP_FLAG,
946 .info = snd_hda_mixer_amp_switch_info,
947 .get = snd_hda_mixer_amp_switch_get,
948 .put = ad1986a_hp_master_sw_put,
949 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
956 * initialization verbs
958 static const struct hda_verb ad1986a_init_verbs[] = {
959 /* Front, Surround, CLFE DAC; mute as default */
960 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
961 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
962 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
964 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
965 /* HP, Line-Out, Surround, CLFE selectors */
966 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
967 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
968 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
969 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
971 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
972 /* Mic selector: Mic 1/2 pin */
973 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
974 /* Line-in selector: Line-in */
975 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
977 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
978 /* Record selector: mic */
979 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
980 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
981 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
982 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
983 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
984 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
985 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
987 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
988 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
989 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
990 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
991 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
992 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
993 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
995 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
996 /* Front, Surround, CLFE Pins */
997 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
998 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
999 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1001 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1003 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1004 /* Line, Aux, CD, Beep-In Pin */
1005 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1006 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1007 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1008 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1009 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1013 static const struct hda_verb ad1986a_ch2_init[] = {
1014 /* Surround out -> Line In */
1015 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1016 /* Line-in selectors */
1017 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
1018 /* CLFE -> Mic in */
1019 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1020 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1021 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1025 static const struct hda_verb ad1986a_ch4_init[] = {
1026 /* Surround out -> Surround */
1027 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1028 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1029 /* CLFE -> Mic in */
1030 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1031 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1035 static const struct hda_verb ad1986a_ch6_init[] = {
1036 /* Surround out -> Surround out */
1037 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1038 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1040 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1041 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1045 static const struct hda_channel_mode ad1986a_modes[3] = {
1046 { 2, ad1986a_ch2_init },
1047 { 4, ad1986a_ch4_init },
1048 { 6, ad1986a_ch6_init },
1051 /* eapd initialization */
1052 static const struct hda_verb ad1986a_eapd_init_verbs[] = {
1053 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1057 static const struct hda_verb ad1986a_automic_verbs[] = {
1058 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1059 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1060 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1061 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1062 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1066 /* Ultra initialization */
1067 static const struct hda_verb ad1986a_ultra_init[] = {
1068 /* eapd initialization */
1069 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1070 /* CLFE -> Mic in */
1071 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1072 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1073 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1077 /* pin sensing on HP jack */
1078 static const struct hda_verb ad1986a_hp_init_verbs[] = {
1079 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1083 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1086 switch (res >> 26) {
1087 case AD1986A_HP_EVENT:
1088 ad1986a_hp_automute(codec);
1090 case AD1986A_MIC_EVENT:
1091 ad1986a_automic(codec);
1096 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1099 ad1986a_hp_automute(codec);
1100 ad1986a_automic(codec);
1111 AD1986A_LAPTOP_EAPD,
1112 AD1986A_LAPTOP_AUTOMUTE,
1115 AD1986A_SAMSUNG_P50,
1119 static const char * const ad1986a_models[AD1986A_MODELS] = {
1120 [AD1986A_AUTO] = "auto",
1121 [AD1986A_6STACK] = "6stack",
1122 [AD1986A_3STACK] = "3stack",
1123 [AD1986A_LAPTOP] = "laptop",
1124 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1125 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1126 [AD1986A_ULTRA] = "ultra",
1127 [AD1986A_SAMSUNG] = "samsung",
1128 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1131 static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1132 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1133 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1134 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1135 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1136 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1137 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1138 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1139 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1140 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1141 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1142 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1143 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1144 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1145 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1146 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1147 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1148 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1149 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1150 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1151 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1152 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1153 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1154 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1155 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1156 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1157 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1158 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1163 static const struct hda_amp_list ad1986a_loopbacks[] = {
1164 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1165 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1166 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1167 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1168 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1173 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1175 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1176 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1178 #endif /* ENABLE_AD_STATIC_QUIRKS */
1180 static int alloc_ad_spec(struct hda_codec *codec)
1182 struct ad198x_spec *spec;
1184 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1188 snd_hda_gen_spec_init(&spec->gen);
1193 * AD1986A fixup codes
1196 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
1197 static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
1198 const struct hda_fixup *fix, int action)
1200 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1201 codec->inv_jack_detect = 1;
1205 AD1986A_FIXUP_INV_JACK_DETECT,
1208 static const struct hda_fixup ad1986a_fixups[] = {
1209 [AD1986A_FIXUP_INV_JACK_DETECT] = {
1210 .type = HDA_FIXUP_FUNC,
1211 .v.func = ad_fixup_inv_jack_detect,
1215 static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
1216 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
1222 static int ad1986a_parse_auto_config(struct hda_codec *codec)
1225 struct ad198x_spec *spec;
1227 err = alloc_ad_spec(codec);
1232 /* AD1986A has the inverted EAPD implementation */
1233 codec->inv_eapd = 1;
1235 spec->gen.mixer_nid = 0x07;
1236 spec->gen.beep_nid = 0x19;
1237 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1239 /* AD1986A has a hardware problem that it can't share a stream
1240 * with multiple output pins. The copy of front to surrounds
1241 * causes noisy or silent outputs at a certain timing, e.g.
1242 * changing the volume.
1243 * So, let's disable the shared stream.
1245 spec->gen.multiout.no_share_stream = 1;
1247 snd_hda_pick_fixup(codec, NULL, ad1986a_fixup_tbl, ad1986a_fixups);
1248 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1250 err = ad198x_parse_auto_config(codec);
1252 snd_hda_gen_free(codec);
1256 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1261 #ifdef ENABLE_AD_STATIC_QUIRKS
1262 static int patch_ad1986a(struct hda_codec *codec)
1264 struct ad198x_spec *spec;
1265 int err, board_config;
1267 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1270 if (board_config < 0) {
1271 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
1273 board_config = AD1986A_AUTO;
1276 if (board_config == AD1986A_AUTO)
1277 return ad1986a_parse_auto_config(codec);
1279 err = alloc_ad_spec(codec);
1284 err = snd_hda_attach_beep_device(codec, 0x19);
1289 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1291 spec->multiout.max_channels = 6;
1292 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1293 spec->multiout.dac_nids = ad1986a_dac_nids;
1294 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1295 spec->num_adc_nids = 1;
1296 spec->adc_nids = ad1986a_adc_nids;
1297 spec->capsrc_nids = ad1986a_capsrc_nids;
1298 spec->input_mux = &ad1986a_capture_source;
1299 spec->num_mixers = 1;
1300 spec->mixers[0] = ad1986a_mixers;
1301 spec->num_init_verbs = 1;
1302 spec->init_verbs[0] = ad1986a_init_verbs;
1304 spec->loopback.amplist = ad1986a_loopbacks;
1306 spec->vmaster_nid = 0x1b;
1307 codec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1309 codec->patch_ops = ad198x_patch_ops;
1311 /* override some parameters */
1312 switch (board_config) {
1313 case AD1986A_3STACK:
1314 spec->num_mixers = 2;
1315 spec->mixers[1] = ad1986a_3st_mixers;
1316 spec->num_init_verbs = 2;
1317 spec->init_verbs[1] = ad1986a_ch2_init;
1318 spec->channel_mode = ad1986a_modes;
1319 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1320 spec->need_dac_fix = 1;
1321 spec->multiout.max_channels = 2;
1322 spec->multiout.num_dacs = 1;
1324 case AD1986A_LAPTOP:
1325 spec->mixers[0] = ad1986a_laptop_mixers;
1326 spec->multiout.max_channels = 2;
1327 spec->multiout.num_dacs = 1;
1328 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1330 case AD1986A_LAPTOP_EAPD:
1331 spec->num_mixers = 3;
1332 spec->mixers[0] = ad1986a_laptop_master_mixers;
1333 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1334 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1335 spec->num_init_verbs = 2;
1336 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1337 spec->multiout.max_channels = 2;
1338 spec->multiout.num_dacs = 1;
1339 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1340 if (!is_jack_available(codec, 0x25))
1341 spec->multiout.dig_out_nid = 0;
1342 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1344 case AD1986A_SAMSUNG:
1345 spec->num_mixers = 2;
1346 spec->mixers[0] = ad1986a_laptop_master_mixers;
1347 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1348 spec->num_init_verbs = 3;
1349 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1350 spec->init_verbs[2] = ad1986a_automic_verbs;
1351 spec->multiout.max_channels = 2;
1352 spec->multiout.num_dacs = 1;
1353 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1354 if (!is_jack_available(codec, 0x25))
1355 spec->multiout.dig_out_nid = 0;
1356 spec->input_mux = &ad1986a_automic_capture_source;
1357 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1358 codec->patch_ops.init = ad1986a_automic_init;
1360 case AD1986A_SAMSUNG_P50:
1361 spec->num_mixers = 2;
1362 spec->mixers[0] = ad1986a_automute_master_mixers;
1363 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1364 spec->num_init_verbs = 4;
1365 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1366 spec->init_verbs[2] = ad1986a_automic_verbs;
1367 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1368 spec->multiout.max_channels = 2;
1369 spec->multiout.num_dacs = 1;
1370 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1371 if (!is_jack_available(codec, 0x25))
1372 spec->multiout.dig_out_nid = 0;
1373 spec->input_mux = &ad1986a_automic_capture_source;
1374 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1375 codec->patch_ops.init = ad1986a_samsung_p50_init;
1377 case AD1986A_LAPTOP_AUTOMUTE:
1378 spec->num_mixers = 3;
1379 spec->mixers[0] = ad1986a_automute_master_mixers;
1380 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1381 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1382 spec->num_init_verbs = 3;
1383 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1384 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1385 spec->multiout.max_channels = 2;
1386 spec->multiout.num_dacs = 1;
1387 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1388 if (!is_jack_available(codec, 0x25))
1389 spec->multiout.dig_out_nid = 0;
1390 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1391 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1392 codec->patch_ops.init = ad1986a_hp_init;
1393 /* Lenovo N100 seems to report the reversed bit
1394 * for HP jack-sensing
1396 spec->inv_jack_detect = 1;
1399 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1400 spec->num_init_verbs = 2;
1401 spec->init_verbs[1] = ad1986a_ultra_init;
1402 spec->multiout.max_channels = 2;
1403 spec->multiout.num_dacs = 1;
1404 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1405 spec->multiout.dig_out_nid = 0;
1409 /* AD1986A has a hardware problem that it can't share a stream
1410 * with multiple output pins. The copy of front to surrounds
1411 * causes noisy or silent outputs at a certain timing, e.g.
1412 * changing the volume.
1413 * So, let's disable the shared stream.
1415 spec->multiout.no_share_stream = 1;
1417 codec->no_trigger_sense = 1;
1418 codec->no_sticky_stream = 1;
1422 #else /* ENABLE_AD_STATIC_QUIRKS */
1423 #define patch_ad1986a ad1986a_parse_auto_config
1424 #endif /* ENABLE_AD_STATIC_QUIRKS */
1430 #ifdef ENABLE_AD_STATIC_QUIRKS
1431 #define AD1983_SPDIF_OUT 0x02
1432 #define AD1983_DAC 0x03
1433 #define AD1983_ADC 0x04
1435 static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1436 static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1437 static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1439 static const struct hda_input_mux ad1983_capture_source = {
1445 { "Mix Mono", 0x3 },
1450 * SPDIF playback route
1452 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1454 static const char * const texts[] = { "PCM", "ADC" };
1456 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1458 uinfo->value.enumerated.items = 2;
1459 if (uinfo->value.enumerated.item > 1)
1460 uinfo->value.enumerated.item = 1;
1461 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1465 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1467 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1468 struct ad198x_spec *spec = codec->spec;
1470 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1474 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1476 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1477 struct ad198x_spec *spec = codec->spec;
1479 if (ucontrol->value.enumerated.item[0] > 1)
1481 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1482 spec->spdif_route = ucontrol->value.enumerated.item[0];
1483 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1484 AC_VERB_SET_CONNECT_SEL,
1491 static const struct snd_kcontrol_new ad1983_mixers[] = {
1492 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1493 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1494 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1495 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1496 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1497 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1498 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1499 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1500 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "Capture Source",
1510 .info = ad198x_mux_enum_info,
1511 .get = ad198x_mux_enum_get,
1512 .put = ad198x_mux_enum_put,
1515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1516 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1517 .info = ad1983_spdif_route_info,
1518 .get = ad1983_spdif_route_get,
1519 .put = ad1983_spdif_route_put,
1524 static const struct hda_verb ad1983_init_verbs[] = {
1525 /* Front, HP, Mono; mute as default */
1526 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1527 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1528 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1529 /* Beep, PCM, Mic, Line-In: mute */
1530 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1531 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1532 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1533 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1534 /* Front, HP selectors; from Mix */
1535 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1536 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1537 /* Mono selector; from Mix */
1538 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1539 /* Mic selector; Mic */
1540 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1541 /* Line-in selector: Line-in */
1542 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1543 /* Mic boost: 0dB */
1544 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1545 /* Record selector: mic */
1546 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1547 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1548 /* SPDIF route: PCM */
1549 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1551 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1553 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1555 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1557 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1559 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1564 static const struct hda_amp_list ad1983_loopbacks[] = {
1565 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1566 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1578 static const char * const ad1983_models[AD1983_MODELS] = {
1579 [AD1983_AUTO] = "auto",
1580 [AD1983_BASIC] = "basic",
1582 #endif /* ENABLE_AD_STATIC_QUIRKS */
1586 * SPDIF mux control for AD1983 auto-parser
1588 static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
1589 struct snd_ctl_elem_info *uinfo)
1591 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1592 struct ad198x_spec *spec = codec->spec;
1593 static const char * const texts2[] = { "PCM", "ADC" };
1594 static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
1595 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1596 int num_conns = snd_hda_get_num_conns(codec, dig_out);
1599 return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
1600 else if (num_conns == 3)
1601 return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
1606 static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
1607 struct snd_ctl_elem_value *ucontrol)
1609 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1610 struct ad198x_spec *spec = codec->spec;
1612 ucontrol->value.enumerated.item[0] = spec->cur_smux;
1616 static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
1617 struct snd_ctl_elem_value *ucontrol)
1619 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1620 struct ad198x_spec *spec = codec->spec;
1621 unsigned int val = ucontrol->value.enumerated.item[0];
1622 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1623 int num_conns = snd_hda_get_num_conns(codec, dig_out);
1625 if (val >= num_conns)
1627 if (spec->cur_smux == val)
1629 spec->cur_smux = val;
1630 snd_hda_codec_write_cache(codec, dig_out, 0,
1631 AC_VERB_SET_CONNECT_SEL, val);
1635 static struct snd_kcontrol_new ad1983_auto_smux_mixer = {
1636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1637 .name = "IEC958 Playback Source",
1638 .info = ad1983_auto_smux_enum_info,
1639 .get = ad1983_auto_smux_enum_get,
1640 .put = ad1983_auto_smux_enum_put,
1643 static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
1645 struct ad198x_spec *spec = codec->spec;
1646 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1651 num_conns = snd_hda_get_num_conns(codec, dig_out);
1652 if (num_conns != 2 && num_conns != 3)
1654 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
1659 static int ad1983_parse_auto_config(struct hda_codec *codec)
1661 struct ad198x_spec *spec;
1664 err = alloc_ad_spec(codec);
1669 spec->gen.beep_nid = 0x10;
1670 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1671 err = ad198x_parse_auto_config(codec);
1674 err = ad1983_add_spdif_mux_ctl(codec);
1680 snd_hda_gen_free(codec);
1684 #ifdef ENABLE_AD_STATIC_QUIRKS
1685 static int patch_ad1983(struct hda_codec *codec)
1687 struct ad198x_spec *spec;
1691 board_config = snd_hda_check_board_config(codec, AD1983_MODELS,
1692 ad1983_models, NULL);
1693 if (board_config < 0) {
1694 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
1696 board_config = AD1983_AUTO;
1699 if (board_config == AD1983_AUTO)
1700 return ad1983_parse_auto_config(codec);
1702 err = alloc_ad_spec(codec);
1707 err = snd_hda_attach_beep_device(codec, 0x10);
1712 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1714 spec->multiout.max_channels = 2;
1715 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1716 spec->multiout.dac_nids = ad1983_dac_nids;
1717 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1718 spec->num_adc_nids = 1;
1719 spec->adc_nids = ad1983_adc_nids;
1720 spec->capsrc_nids = ad1983_capsrc_nids;
1721 spec->input_mux = &ad1983_capture_source;
1722 spec->num_mixers = 1;
1723 spec->mixers[0] = ad1983_mixers;
1724 spec->num_init_verbs = 1;
1725 spec->init_verbs[0] = ad1983_init_verbs;
1726 spec->spdif_route = 0;
1728 spec->loopback.amplist = ad1983_loopbacks;
1730 spec->vmaster_nid = 0x05;
1732 codec->patch_ops = ad198x_patch_ops;
1734 codec->no_trigger_sense = 1;
1735 codec->no_sticky_stream = 1;
1739 #else /* ENABLE_AD_STATIC_QUIRKS */
1740 #define patch_ad1983 ad1983_parse_auto_config
1741 #endif /* ENABLE_AD_STATIC_QUIRKS */
1745 * AD1981 HD specific
1748 #ifdef ENABLE_AD_STATIC_QUIRKS
1749 #define AD1981_SPDIF_OUT 0x02
1750 #define AD1981_DAC 0x03
1751 #define AD1981_ADC 0x04
1753 static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1754 static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1755 static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1757 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1758 static const struct hda_input_mux ad1981_capture_source = {
1761 { "Front Mic", 0x0 },
1764 { "Mix Mono", 0x3 },
1771 static const struct snd_kcontrol_new ad1981_mixers[] = {
1772 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1773 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1774 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1775 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1776 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1777 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1778 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1779 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1780 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1781 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1782 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1783 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1784 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1785 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1786 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1787 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1788 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1789 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1790 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1791 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1792 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1793 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1795 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1796 .name = "Capture Source",
1797 .info = ad198x_mux_enum_info,
1798 .get = ad198x_mux_enum_get,
1799 .put = ad198x_mux_enum_put,
1801 /* identical with AD1983 */
1803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1804 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1805 .info = ad1983_spdif_route_info,
1806 .get = ad1983_spdif_route_get,
1807 .put = ad1983_spdif_route_put,
1812 static const struct hda_verb ad1981_init_verbs[] = {
1813 /* Front, HP, Mono; mute as default */
1814 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1815 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1816 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1817 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1818 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1819 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1820 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1821 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1822 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1823 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1824 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1825 /* Front, HP selectors; from Mix */
1826 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1827 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1828 /* Mono selector; from Mix */
1829 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1830 /* Mic Mixer; select Front Mic */
1831 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1832 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1833 /* Mic boost: 0dB */
1834 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1835 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1836 /* Record selector: Front mic */
1837 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1838 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1839 /* SPDIF route: PCM */
1840 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1842 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1844 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1846 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1847 /* Front & Rear Mic Pins */
1848 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1849 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1851 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1853 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1854 /* Line-Out as Input: disabled */
1855 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1860 static const struct hda_amp_list ad1981_loopbacks[] = {
1861 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1862 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1863 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1864 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1865 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1871 * Patch for HP nx6320
1873 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1874 * speaker output enabled _and_ mute-LED off.
1877 #define AD1981_HP_EVENT 0x37
1878 #define AD1981_MIC_EVENT 0x38
1880 static const struct hda_verb ad1981_hp_init_verbs[] = {
1881 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1882 /* pin sensing on HP and Mic jacks */
1883 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1884 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1888 /* turn on/off EAPD (+ mute HP) as a master switch */
1889 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1890 struct snd_ctl_elem_value *ucontrol)
1892 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1893 struct ad198x_spec *spec = codec->spec;
1895 if (! ad198x_eapd_put(kcontrol, ucontrol))
1897 /* change speaker pin appropriately */
1898 snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);
1899 /* toggle HP mute appropriately */
1900 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1902 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1906 /* bind volumes of both NID 0x05 and 0x06 */
1907 static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1908 .ops = &snd_hda_bind_vol,
1910 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1911 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1916 /* mute internal speaker if HP is plugged */
1917 static void ad1981_hp_automute(struct hda_codec *codec)
1919 unsigned int present;
1921 present = snd_hda_jack_detect(codec, 0x06);
1922 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1923 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1926 /* toggle input of built-in and mic jack appropriately */
1927 static void ad1981_hp_automic(struct hda_codec *codec)
1929 static const struct hda_verb mic_jack_on[] = {
1930 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1931 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1934 static const struct hda_verb mic_jack_off[] = {
1935 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1936 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1939 unsigned int present;
1941 present = snd_hda_jack_detect(codec, 0x08);
1943 snd_hda_sequence_write(codec, mic_jack_on);
1945 snd_hda_sequence_write(codec, mic_jack_off);
1948 /* unsolicited event for HP jack sensing */
1949 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1954 case AD1981_HP_EVENT:
1955 ad1981_hp_automute(codec);
1957 case AD1981_MIC_EVENT:
1958 ad1981_hp_automic(codec);
1963 static const struct hda_input_mux ad1981_hp_capture_source = {
1967 { "Dock Mic", 0x1 },
1972 static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
1973 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1975 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1976 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1977 .name = "Master Playback Switch",
1978 .info = ad198x_eapd_info,
1979 .get = ad198x_eapd_get,
1980 .put = ad1981_hp_master_sw_put,
1981 .private_value = 0x05,
1983 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1984 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1986 /* FIXME: analog mic/line loopback doesn't work with my tests...
1987 * (although recording is OK)
1989 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1990 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1991 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1992 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1993 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1994 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1995 /* FIXME: does this laptop have analog CD connection? */
1996 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1997 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1999 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
2000 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
2001 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
2002 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
2004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2005 .name = "Capture Source",
2006 .info = ad198x_mux_enum_info,
2007 .get = ad198x_mux_enum_get,
2008 .put = ad198x_mux_enum_put,
2013 /* initialize jack-sensing, too */
2014 static int ad1981_hp_init(struct hda_codec *codec)
2017 ad1981_hp_automute(codec);
2018 ad1981_hp_automic(codec);
2022 /* configuration for Toshiba Laptops */
2023 static const struct hda_verb ad1981_toshiba_init_verbs[] = {
2024 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
2025 /* pin sensing on HP and Mic jacks */
2026 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
2027 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
2031 static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
2032 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
2033 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
2037 /* configuration for Lenovo Thinkpad T60 */
2038 static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
2039 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2040 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
2041 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
2042 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
2043 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
2044 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
2045 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2046 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
2047 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
2048 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
2049 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
2051 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2052 .name = "Capture Source",
2053 .info = ad198x_mux_enum_info,
2054 .get = ad198x_mux_enum_get,
2055 .put = ad198x_mux_enum_put,
2057 /* identical with AD1983 */
2059 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2060 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2061 .info = ad1983_spdif_route_info,
2062 .get = ad1983_spdif_route_get,
2063 .put = ad1983_spdif_route_put,
2068 static const struct hda_input_mux ad1981_thinkpad_capture_source = {
2087 static const char * const ad1981_models[AD1981_MODELS] = {
2088 [AD1981_AUTO] = "auto",
2090 [AD1981_THINKPAD] = "thinkpad",
2091 [AD1981_BASIC] = "basic",
2092 [AD1981_TOSHIBA] = "toshiba"
2095 static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
2096 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
2097 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
2099 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
2100 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
2101 /* Lenovo Thinkpad T60/X60/Z6xx */
2102 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
2103 /* HP nx6320 (reversed SSID, H/W bug) */
2104 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
2107 #endif /* ENABLE_AD_STATIC_QUIRKS */
2110 /* follow EAPD via vmaster hook */
2111 static void ad_vmaster_eapd_hook(void *private_data, int enabled)
2113 struct hda_codec *codec = private_data;
2114 struct ad198x_spec *spec = codec->spec;
2115 snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
2116 AC_VERB_SET_EAPD_BTLENABLE,
2117 enabled ? 0x02 : 0x00);
2120 static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
2121 const struct hda_fixup *fix, int action)
2123 struct ad198x_spec *spec = codec->spec;
2125 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2126 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
2127 spec->eapd_nid = 0x05;
2131 /* set the upper-limit for mixer amp to 0dB for avoiding the possible
2132 * damage by overloading
2134 static void ad1981_fixup_amp_override(struct hda_codec *codec,
2135 const struct hda_fixup *fix, int action)
2137 if (action == HDA_FIXUP_ACT_PRE_PROBE)
2138 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2139 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2140 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2141 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2142 (1 << AC_AMPCAP_MUTE_SHIFT));
2146 AD1981_FIXUP_AMP_OVERRIDE,
2147 AD1981_FIXUP_HP_EAPD,
2150 static const struct hda_fixup ad1981_fixups[] = {
2151 [AD1981_FIXUP_AMP_OVERRIDE] = {
2152 .type = HDA_FIXUP_FUNC,
2153 .v.func = ad1981_fixup_amp_override,
2155 [AD1981_FIXUP_HP_EAPD] = {
2156 .type = HDA_FIXUP_FUNC,
2157 .v.func = ad1981_fixup_hp_eapd,
2159 .chain_id = AD1981_FIXUP_AMP_OVERRIDE,
2163 static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
2164 SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2165 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
2166 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2167 /* HP nx6320 (reversed SSID, H/W bug) */
2168 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
2172 static int ad1981_parse_auto_config(struct hda_codec *codec)
2174 struct ad198x_spec *spec;
2177 err = alloc_ad_spec(codec);
2182 spec->gen.mixer_nid = 0x0e;
2183 spec->gen.beep_nid = 0x10;
2184 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2186 snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
2187 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
2189 err = ad198x_parse_auto_config(codec);
2192 err = ad1983_add_spdif_mux_ctl(codec);
2196 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
2201 snd_hda_gen_free(codec);
2205 #ifdef ENABLE_AD_STATIC_QUIRKS
2206 static int patch_ad1981(struct hda_codec *codec)
2208 struct ad198x_spec *spec;
2209 int err, board_config;
2211 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
2214 if (board_config < 0) {
2215 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
2217 board_config = AD1981_AUTO;
2220 if (board_config == AD1981_AUTO)
2221 return ad1981_parse_auto_config(codec);
2223 err = alloc_ad_spec(codec);
2228 err = snd_hda_attach_beep_device(codec, 0x10);
2233 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2235 spec->multiout.max_channels = 2;
2236 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
2237 spec->multiout.dac_nids = ad1981_dac_nids;
2238 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
2239 spec->num_adc_nids = 1;
2240 spec->adc_nids = ad1981_adc_nids;
2241 spec->capsrc_nids = ad1981_capsrc_nids;
2242 spec->input_mux = &ad1981_capture_source;
2243 spec->num_mixers = 1;
2244 spec->mixers[0] = ad1981_mixers;
2245 spec->num_init_verbs = 1;
2246 spec->init_verbs[0] = ad1981_init_verbs;
2247 spec->spdif_route = 0;
2249 spec->loopback.amplist = ad1981_loopbacks;
2251 spec->vmaster_nid = 0x05;
2253 codec->patch_ops = ad198x_patch_ops;
2255 /* override some parameters */
2256 switch (board_config) {
2258 spec->mixers[0] = ad1981_hp_mixers;
2259 spec->num_init_verbs = 2;
2260 spec->init_verbs[1] = ad1981_hp_init_verbs;
2261 if (!is_jack_available(codec, 0x0a))
2262 spec->multiout.dig_out_nid = 0;
2263 spec->input_mux = &ad1981_hp_capture_source;
2265 codec->patch_ops.init = ad1981_hp_init;
2266 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2267 /* set the upper-limit for mixer amp to 0dB for avoiding the
2268 * possible damage by overloading
2270 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2271 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2272 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2273 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2274 (1 << AC_AMPCAP_MUTE_SHIFT));
2276 case AD1981_THINKPAD:
2277 spec->mixers[0] = ad1981_thinkpad_mixers;
2278 spec->input_mux = &ad1981_thinkpad_capture_source;
2279 /* set the upper-limit for mixer amp to 0dB for avoiding the
2280 * possible damage by overloading
2282 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2283 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2284 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2285 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2286 (1 << AC_AMPCAP_MUTE_SHIFT));
2288 case AD1981_TOSHIBA:
2289 spec->mixers[0] = ad1981_hp_mixers;
2290 spec->mixers[1] = ad1981_toshiba_mixers;
2291 spec->num_init_verbs = 2;
2292 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
2293 spec->multiout.dig_out_nid = 0;
2294 spec->input_mux = &ad1981_hp_capture_source;
2295 codec->patch_ops.init = ad1981_hp_init;
2296 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2300 codec->no_trigger_sense = 1;
2301 codec->no_sticky_stream = 1;
2305 #else /* ENABLE_AD_STATIC_QUIRKS */
2306 #define patch_ad1981 ad1981_parse_auto_config
2307 #endif /* ENABLE_AD_STATIC_QUIRKS */
2313 * Output pins and routes
2315 * Pin Mix Sel DAC (*)
2316 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
2317 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
2318 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
2319 * port-D 0x12 (mute/hp) <- 0x29 <- 04
2320 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
2321 * port-F 0x16 (mute) <- 0x2a <- 06
2322 * port-G 0x24 (mute) <- 0x27 <- 05
2323 * port-H 0x25 (mute) <- 0x28 <- 0a
2324 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
2326 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
2327 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
2329 * Input pins and routes
2331 * pin boost mix input # / adc input #
2332 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
2333 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
2334 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
2335 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
2336 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
2337 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
2338 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
2339 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2343 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2344 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2346 * Inputs of Analog Mix (0x20)
2347 * 0:Port-B (front mic)
2348 * 1:Port-C/G/H (line-in)
2350 * 3:Port-D (line-in/2)
2351 * 4:Port-E/G/H (mic-in)
2352 * 5:Port-F (mic2-in)
2358 * 1:Port-B (front mic-in)
2359 * 2:Port-C (line-in)
2360 * 3:Port-F (mic2-in)
2365 * 8:Port-D (line-in/2)
2368 * Proposed pin assignments by the datasheet
2371 * Port-A front headphone
2381 * Port-A front headphone
2383 * C rear line-in/surround
2385 * E rear mic-in/CLFE
2391 * D internal speaker (with EAPD)
2392 * E/F quad mic array
2396 #ifdef ENABLE_AD_STATIC_QUIRKS
2409 /* reivision id to check workarounds */
2410 #define AD1988A_REV2 0x100200
2412 #define is_rev2(codec) \
2413 ((codec)->vendor_id == 0x11d41988 && \
2414 (codec)->revision_id == AD1988A_REV2)
2420 static const hda_nid_t ad1988_6stack_dac_nids[4] = {
2421 0x04, 0x06, 0x05, 0x0a
2424 static const hda_nid_t ad1988_3stack_dac_nids[3] = {
2428 /* for AD1988A revision-2, DAC2-4 are swapped */
2429 static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2430 0x04, 0x05, 0x0a, 0x06
2433 static const hda_nid_t ad1988_alt_dac_nid[1] = {
2437 static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2441 static const hda_nid_t ad1988_adc_nids[3] = {
2445 static const hda_nid_t ad1988_capsrc_nids[3] = {
2449 #define AD1988_SPDIF_OUT 0x02
2450 #define AD1988_SPDIF_OUT_HDMI 0x0b
2451 #define AD1988_SPDIF_IN 0x07
2453 static const hda_nid_t ad1989b_slave_dig_outs[] = {
2454 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2457 static const struct hda_input_mux ad1988_6stack_capture_source = {
2460 { "Front Mic", 0x1 }, /* port-B */
2461 { "Line", 0x2 }, /* port-C */
2462 { "Mic", 0x4 }, /* port-E */
2468 static const struct hda_input_mux ad1988_laptop_capture_source = {
2471 { "Mic/Line", 0x1 }, /* port-B */
2479 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2480 struct snd_ctl_elem_info *uinfo)
2482 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2483 struct ad198x_spec *spec = codec->spec;
2484 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2485 spec->num_channel_mode);
2488 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2489 struct snd_ctl_elem_value *ucontrol)
2491 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2492 struct ad198x_spec *spec = codec->spec;
2493 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2494 spec->num_channel_mode, spec->multiout.max_channels);
2497 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2498 struct snd_ctl_elem_value *ucontrol)
2500 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2501 struct ad198x_spec *spec = codec->spec;
2502 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2503 spec->num_channel_mode,
2504 &spec->multiout.max_channels);
2505 if (err >= 0 && spec->need_dac_fix)
2506 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2511 static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2512 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2513 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2514 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2515 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2516 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2520 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2521 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2522 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2523 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2524 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2525 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2529 static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2530 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2531 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2532 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2533 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2534 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2535 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2536 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2537 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2539 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2540 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2541 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2542 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2543 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2544 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2545 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2546 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2548 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2549 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2551 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2552 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2557 static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2558 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2559 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2560 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2561 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2565 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2566 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2567 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2568 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2569 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2573 static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2574 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2575 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2576 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2577 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2578 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2579 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2580 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2582 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2583 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2584 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2585 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2586 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2587 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2588 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2589 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2591 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2592 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2594 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2595 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2598 .name = "Channel Mode",
2599 .info = ad198x_ch_mode_info,
2600 .get = ad198x_ch_mode_get,
2601 .put = ad198x_ch_mode_put,
2608 static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2609 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2610 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2611 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2612 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2614 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2615 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2616 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2617 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2618 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2619 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2621 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2622 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2624 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2627 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2628 .name = "External Amplifier",
2629 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2630 .info = ad198x_eapd_info,
2631 .get = ad198x_eapd_get,
2632 .put = ad198x_eapd_put,
2633 .private_value = 0x12, /* port-D */
2640 static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
2641 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2642 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2643 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2644 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2645 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2646 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2649 /* The multiple "Capture Source" controls confuse alsamixer
2650 * So call somewhat different..
2652 /* .name = "Capture Source", */
2653 .name = "Input Source",
2655 .info = ad198x_mux_enum_info,
2656 .get = ad198x_mux_enum_get,
2657 .put = ad198x_mux_enum_put,
2662 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2663 struct snd_ctl_elem_info *uinfo)
2665 static const char * const texts[] = {
2666 "PCM", "ADC1", "ADC2", "ADC3"
2668 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2670 uinfo->value.enumerated.items = 4;
2671 if (uinfo->value.enumerated.item >= 4)
2672 uinfo->value.enumerated.item = 3;
2673 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2677 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2678 struct snd_ctl_elem_value *ucontrol)
2680 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2683 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2686 ucontrol->value.enumerated.item[0] = 0;
2688 sel = snd_hda_codec_read(codec, 0x0b, 0,
2689 AC_VERB_GET_CONNECT_SEL, 0);
2694 ucontrol->value.enumerated.item[0] = sel;
2699 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2700 struct snd_ctl_elem_value *ucontrol)
2702 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2703 unsigned int val, sel;
2706 val = ucontrol->value.enumerated.item[0];
2710 sel = snd_hda_codec_read(codec, 0x1d, 0,
2711 AC_VERB_GET_AMP_GAIN_MUTE,
2713 change = sel & 0x80;
2715 snd_hda_codec_write_cache(codec, 0x1d, 0,
2716 AC_VERB_SET_AMP_GAIN_MUTE,
2718 snd_hda_codec_write_cache(codec, 0x1d, 0,
2719 AC_VERB_SET_AMP_GAIN_MUTE,
2723 sel = snd_hda_codec_read(codec, 0x1d, 0,
2724 AC_VERB_GET_AMP_GAIN_MUTE,
2725 AC_AMP_GET_INPUT | 0x01);
2726 change = sel & 0x80;
2728 snd_hda_codec_write_cache(codec, 0x1d, 0,
2729 AC_VERB_SET_AMP_GAIN_MUTE,
2731 snd_hda_codec_write_cache(codec, 0x1d, 0,
2732 AC_VERB_SET_AMP_GAIN_MUTE,
2735 sel = snd_hda_codec_read(codec, 0x0b, 0,
2736 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2737 change |= sel != val;
2739 snd_hda_codec_write_cache(codec, 0x0b, 0,
2740 AC_VERB_SET_CONNECT_SEL,
2746 static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2747 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2749 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2750 .name = "IEC958 Playback Source",
2751 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2752 .info = ad1988_spdif_playback_source_info,
2753 .get = ad1988_spdif_playback_source_get,
2754 .put = ad1988_spdif_playback_source_put,
2759 static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2760 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2764 static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2765 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2766 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2771 * initialization verbs
2775 * for 6-stack (+dig)
2777 static const struct hda_verb ad1988_6stack_init_verbs[] = {
2778 /* Front, Surround, CLFE, side DAC; unmute as default */
2779 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2780 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2781 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2782 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2783 /* Port-A front headphon path */
2784 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2786 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2787 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2788 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2789 /* Port-D line-out path */
2790 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2791 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2792 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2793 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2794 /* Port-F surround path */
2795 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2796 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2797 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2798 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2799 /* Port-G CLFE path */
2800 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2801 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2802 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2803 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2804 /* Port-H side path */
2805 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2806 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2807 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2808 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2810 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2811 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2812 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2813 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2814 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2815 /* Port-B front mic-in path */
2816 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2817 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2818 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2819 /* Port-C line-in path */
2820 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2821 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2822 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2823 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2824 /* Port-E mic-in path */
2825 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2826 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2827 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2828 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2829 /* Analog CD Input */
2830 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2831 /* Analog Mix output amp */
2832 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2837 static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
2838 /* Headphone; unmute as default */
2839 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2840 /* Port-A front headphon path */
2841 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2844 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2845 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2850 static const struct hda_verb ad1988_capture_init_verbs[] = {
2851 /* mute analog mix */
2852 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2853 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2854 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2855 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2856 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2857 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2858 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2859 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2860 /* select ADCs - front-mic */
2861 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2862 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2863 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2868 static const struct hda_verb ad1988_spdif_init_verbs[] = {
2870 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2871 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2872 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2873 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2875 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2880 static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
2881 /* unmute SPDIF input pin */
2882 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2886 /* AD1989 has no ADC -> SPDIF route */
2887 static const struct hda_verb ad1989_spdif_init_verbs[] = {
2888 /* SPDIF-1 out pin */
2889 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2890 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2891 /* SPDIF-2/HDMI out pin */
2892 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2893 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2898 * verbs for 3stack (+dig)
2900 static const struct hda_verb ad1988_3stack_ch2_init[] = {
2901 /* set port-C to line-in */
2902 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2903 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2904 /* set port-E to mic-in */
2905 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2906 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2910 static const struct hda_verb ad1988_3stack_ch6_init[] = {
2911 /* set port-C to surround out */
2912 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2913 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2914 /* set port-E to CLFE out */
2915 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2916 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2920 static const struct hda_channel_mode ad1988_3stack_modes[2] = {
2921 { 2, ad1988_3stack_ch2_init },
2922 { 6, ad1988_3stack_ch6_init },
2925 static const struct hda_verb ad1988_3stack_init_verbs[] = {
2926 /* Front, Surround, CLFE, side DAC; unmute as default */
2927 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2928 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2929 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2930 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2931 /* Port-A front headphon path */
2932 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2933 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2934 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2935 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2936 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2937 /* Port-D line-out path */
2938 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2939 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2940 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2941 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2943 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2944 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2945 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2946 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2947 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2948 /* Port-B front mic-in path */
2949 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2950 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2951 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2952 /* Port-C line-in/surround path - 6ch mode as default */
2953 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2954 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2955 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2956 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2957 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2958 /* Port-E mic-in/CLFE path - 6ch mode as default */
2959 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2960 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2961 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2962 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2963 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2964 /* mute analog mix */
2965 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2966 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2967 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2968 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2969 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2970 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2971 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2972 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2973 /* select ADCs - front-mic */
2974 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2975 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2976 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2977 /* Analog Mix output amp */
2978 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2983 * verbs for laptop mode (+dig)
2985 static const struct hda_verb ad1988_laptop_hp_on[] = {
2986 /* unmute port-A and mute port-D */
2987 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2988 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2991 static const struct hda_verb ad1988_laptop_hp_off[] = {
2992 /* mute port-A and unmute port-D */
2993 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2994 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2998 #define AD1988_HP_EVENT 0x01
3000 static const struct hda_verb ad1988_laptop_init_verbs[] = {
3001 /* Front, Surround, CLFE, side DAC; unmute as default */
3002 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3003 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3004 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3005 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3006 /* Port-A front headphon path */
3007 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
3008 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3009 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3010 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3011 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3012 /* unsolicited event for pin-sense */
3013 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
3014 /* Port-D line-out path + EAPD */
3015 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3016 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3017 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3018 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3019 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
3021 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
3022 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3023 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3024 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3025 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
3026 /* Port-B mic-in path */
3027 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3028 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3029 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3030 /* Port-C docking station - try to output */
3031 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3032 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3033 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3034 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
3035 /* mute analog mix */
3036 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3037 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3038 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3039 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3040 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3041 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3042 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3043 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3044 /* select ADCs - mic */
3045 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
3046 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
3047 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3048 /* Analog Mix output amp */
3049 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3053 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
3055 if ((res >> 26) != AD1988_HP_EVENT)
3057 if (snd_hda_jack_detect(codec, 0x11))
3058 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
3060 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
3064 static const struct hda_amp_list ad1988_loopbacks[] = {
3065 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3066 { 0x20, HDA_INPUT, 1 }, /* Line */
3067 { 0x20, HDA_INPUT, 4 }, /* Mic */
3068 { 0x20, HDA_INPUT, 6 }, /* CD */
3072 #endif /* ENABLE_AD_STATIC_QUIRKS */
3074 static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
3075 struct snd_ctl_elem_info *uinfo)
3077 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3078 static const char * const texts[] = {
3079 "PCM", "ADC1", "ADC2", "ADC3",
3081 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3084 return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
3087 static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
3088 struct snd_ctl_elem_value *ucontrol)
3090 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3091 struct ad198x_spec *spec = codec->spec;
3093 ucontrol->value.enumerated.item[0] = spec->cur_smux;
3097 static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
3098 struct snd_ctl_elem_value *ucontrol)
3100 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3101 struct ad198x_spec *spec = codec->spec;
3102 unsigned int val = ucontrol->value.enumerated.item[0];
3103 struct nid_path *path;
3104 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3106 if (val >= num_conns)
3108 if (spec->cur_smux == val)
3111 mutex_lock(&codec->control_mutex);
3112 codec->cached_write = 1;
3113 path = snd_hda_get_path_from_idx(codec,
3114 spec->smux_paths[spec->cur_smux]);
3116 snd_hda_activate_path(codec, path, false, true);
3117 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
3119 snd_hda_activate_path(codec, path, true, true);
3120 spec->cur_smux = val;
3121 codec->cached_write = 0;
3122 mutex_unlock(&codec->control_mutex);
3123 snd_hda_codec_flush_cache(codec); /* flush the updates */
3127 static struct snd_kcontrol_new ad1988_auto_smux_mixer = {
3128 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3129 .name = "IEC958 Playback Source",
3130 .info = ad1988_auto_smux_enum_info,
3131 .get = ad1988_auto_smux_enum_get,
3132 .put = ad1988_auto_smux_enum_put,
3135 static int ad1988_auto_init(struct hda_codec *codec)
3137 struct ad198x_spec *spec = codec->spec;
3140 err = snd_hda_gen_init(codec);
3143 if (!spec->gen.autocfg.dig_outs)
3146 for (i = 0; i < 4; i++) {
3147 struct nid_path *path;
3148 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
3150 snd_hda_activate_path(codec, path, path->active, false);
3156 static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
3158 struct ad198x_spec *spec = codec->spec;
3160 /* we create four static faked paths, since AD codecs have odd
3161 * widget connections regarding the SPDIF out source
3163 static struct nid_path fake_paths[4] = {
3166 .path = { 0x02, 0x1d, 0x1b },
3168 .multi = { 0, 0, 0 },
3172 .path = { 0x08, 0x0b, 0x1d, 0x1b },
3173 .idx = { 0, 0, 1, 0 },
3174 .multi = { 0, 1, 0, 0 },
3178 .path = { 0x09, 0x0b, 0x1d, 0x1b },
3179 .idx = { 0, 1, 1, 0 },
3180 .multi = { 0, 1, 0, 0 },
3184 .path = { 0x0f, 0x0b, 0x1d, 0x1b },
3185 .idx = { 0, 2, 1, 0 },
3186 .multi = { 0, 1, 0, 0 },
3190 /* SPDIF source mux appears to be present only on AD1988A */
3191 if (!spec->gen.autocfg.dig_outs ||
3192 get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
3195 num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3196 if (num_conns != 3 && num_conns != 4)
3199 for (i = 0; i < num_conns; i++) {
3200 struct nid_path *path = snd_array_new(&spec->gen.paths);
3203 *path = fake_paths[i];
3206 spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
3209 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
3212 codec->patch_ops.init = ad1988_auto_init;
3220 static int ad1988_parse_auto_config(struct hda_codec *codec)
3222 struct ad198x_spec *spec;
3225 err = alloc_ad_spec(codec);
3230 spec->gen.mixer_nid = 0x20;
3231 spec->gen.mixer_merge_nid = 0x21;
3232 spec->gen.beep_nid = 0x10;
3233 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3234 err = ad198x_parse_auto_config(codec);
3237 err = ad1988_add_spdif_mux_ctl(codec);
3243 snd_hda_gen_free(codec);
3250 #ifdef ENABLE_AD_STATIC_QUIRKS
3251 static const char * const ad1988_models[AD1988_MODEL_LAST] = {
3252 [AD1988_6STACK] = "6stack",
3253 [AD1988_6STACK_DIG] = "6stack-dig",
3254 [AD1988_3STACK] = "3stack",
3255 [AD1988_3STACK_DIG] = "3stack-dig",
3256 [AD1988_LAPTOP] = "laptop",
3257 [AD1988_LAPTOP_DIG] = "laptop-dig",
3258 [AD1988_AUTO] = "auto",
3261 static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
3262 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3263 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3264 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3265 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
3266 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3270 static int patch_ad1988(struct hda_codec *codec)
3272 struct ad198x_spec *spec;
3273 int err, board_config;
3275 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3276 ad1988_models, ad1988_cfg_tbl);
3277 if (board_config < 0) {
3278 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3280 board_config = AD1988_AUTO;
3283 if (board_config == AD1988_AUTO)
3284 return ad1988_parse_auto_config(codec);
3286 err = alloc_ad_spec(codec);
3292 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3294 err = snd_hda_attach_beep_device(codec, 0x10);
3299 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3301 if (!spec->multiout.hp_nid)
3302 spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
3303 switch (board_config) {
3305 case AD1988_6STACK_DIG:
3306 spec->multiout.max_channels = 8;
3307 spec->multiout.num_dacs = 4;
3309 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3311 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3312 spec->input_mux = &ad1988_6stack_capture_source;
3313 spec->num_mixers = 2;
3315 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3317 spec->mixers[0] = ad1988_6stack_mixers1;
3318 spec->mixers[1] = ad1988_6stack_mixers2;
3319 spec->num_init_verbs = 1;
3320 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3321 if (board_config == AD1988_6STACK_DIG) {
3322 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3323 spec->dig_in_nid = AD1988_SPDIF_IN;
3327 case AD1988_3STACK_DIG:
3328 spec->multiout.max_channels = 6;
3329 spec->multiout.num_dacs = 3;
3331 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3333 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3334 spec->input_mux = &ad1988_6stack_capture_source;
3335 spec->channel_mode = ad1988_3stack_modes;
3336 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3337 spec->num_mixers = 2;
3339 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3341 spec->mixers[0] = ad1988_3stack_mixers1;
3342 spec->mixers[1] = ad1988_3stack_mixers2;
3343 spec->num_init_verbs = 1;
3344 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3345 if (board_config == AD1988_3STACK_DIG)
3346 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3349 case AD1988_LAPTOP_DIG:
3350 spec->multiout.max_channels = 2;
3351 spec->multiout.num_dacs = 1;
3352 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3353 spec->input_mux = &ad1988_laptop_capture_source;
3354 spec->num_mixers = 1;
3355 spec->mixers[0] = ad1988_laptop_mixers;
3356 codec->inv_eapd = 1; /* inverted EAPD */
3357 spec->num_init_verbs = 1;
3358 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3359 if (board_config == AD1988_LAPTOP_DIG)
3360 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3364 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3365 spec->adc_nids = ad1988_adc_nids;
3366 spec->capsrc_nids = ad1988_capsrc_nids;
3367 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3368 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3369 if (spec->multiout.dig_out_nid) {
3370 if (codec->vendor_id >= 0x11d4989a) {
3371 spec->mixers[spec->num_mixers++] =
3372 ad1989_spdif_out_mixers;
3373 spec->init_verbs[spec->num_init_verbs++] =
3374 ad1989_spdif_init_verbs;
3375 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3377 spec->mixers[spec->num_mixers++] =
3378 ad1988_spdif_out_mixers;
3379 spec->init_verbs[spec->num_init_verbs++] =
3380 ad1988_spdif_init_verbs;
3383 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3384 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3385 spec->init_verbs[spec->num_init_verbs++] =
3386 ad1988_spdif_in_init_verbs;
3389 codec->patch_ops = ad198x_patch_ops;
3390 switch (board_config) {
3392 case AD1988_LAPTOP_DIG:
3393 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3397 spec->loopback.amplist = ad1988_loopbacks;
3399 spec->vmaster_nid = 0x04;
3401 codec->no_trigger_sense = 1;
3402 codec->no_sticky_stream = 1;
3406 #else /* ENABLE_AD_STATIC_QUIRKS */
3407 #define patch_ad1988 ad1988_parse_auto_config
3408 #endif /* ENABLE_AD_STATIC_QUIRKS */
3414 * port-B - front line/mic-in
3415 * port-E - aux in/out
3416 * port-F - aux in/out
3417 * port-C - rear line/mic-in
3418 * port-D - rear line/hp-out
3419 * port-A - front line/hp-out
3421 * AD1984 = AD1884 + two digital mic-ins
3424 * For simplicity, we share the single DAC for both HP and line-outs
3425 * right now. The inidividual playbacks could be easily implemented,
3426 * but no build-up framework is given, so far.
3429 #ifdef ENABLE_AD_STATIC_QUIRKS
3430 static const hda_nid_t ad1884_dac_nids[1] = {
3434 static const hda_nid_t ad1884_adc_nids[2] = {
3438 static const hda_nid_t ad1884_capsrc_nids[2] = {
3442 #define AD1884_SPDIF_OUT 0x02
3444 static const struct hda_input_mux ad1884_capture_source = {
3447 { "Front Mic", 0x0 },
3454 static const struct snd_kcontrol_new ad1884_base_mixers[] = {
3455 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3456 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3457 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3458 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3459 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3460 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3461 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3462 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3464 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3465 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3466 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3467 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3468 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3469 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3470 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3471 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3472 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3475 /* The multiple "Capture Source" controls confuse alsamixer
3476 * So call somewhat different..
3478 /* .name = "Capture Source", */
3479 .name = "Input Source",
3481 .info = ad198x_mux_enum_info,
3482 .get = ad198x_mux_enum_get,
3483 .put = ad198x_mux_enum_put,
3485 /* SPDIF controls */
3486 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3489 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3490 /* identical with ad1983 */
3491 .info = ad1983_spdif_route_info,
3492 .get = ad1983_spdif_route_get,
3493 .put = ad1983_spdif_route_put,
3498 static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3499 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3500 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3501 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3503 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3509 * initialization verbs
3511 static const struct hda_verb ad1884_init_verbs[] = {
3512 /* DACs; mute as default */
3513 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3514 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3515 /* Port-A (HP) mixer */
3516 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3517 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3519 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3520 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3521 /* HP selector - select DAC2 */
3522 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3523 /* Port-D (Line-out) mixer */
3524 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3525 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3527 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3528 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3529 /* Mono-out mixer */
3530 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3531 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3533 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3534 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3536 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3537 /* Port-B (front mic) pin */
3538 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3539 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3540 /* Port-C (rear mic) pin */
3541 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3542 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543 /* Analog mixer; mute as default */
3544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3548 /* Analog Mix output amp */
3549 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3550 /* SPDIF output selector */
3551 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3552 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3557 static const struct hda_amp_list ad1884_loopbacks[] = {
3558 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3559 { 0x20, HDA_INPUT, 1 }, /* Mic */
3560 { 0x20, HDA_INPUT, 2 }, /* CD */
3561 { 0x20, HDA_INPUT, 4 }, /* Docking */
3566 static const char * const ad1884_slave_vols[] = {
3567 "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
3568 "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958",
3578 static const char * const ad1884_models[AD1884_MODELS] = {
3579 [AD1884_AUTO] = "auto",
3580 [AD1884_BASIC] = "basic",
3582 #endif /* ENABLE_AD_STATIC_QUIRKS */
3585 /* set the upper-limit for mixer amp to 0dB for avoiding the possible
3586 * damage by overloading
3588 static void ad1884_fixup_amp_override(struct hda_codec *codec,
3589 const struct hda_fixup *fix, int action)
3591 if (action == HDA_FIXUP_ACT_PRE_PROBE)
3592 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
3593 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
3594 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
3595 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
3596 (1 << AC_AMPCAP_MUTE_SHIFT));
3599 static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
3600 const struct hda_fixup *fix, int action)
3602 struct ad198x_spec *spec = codec->spec;
3604 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3605 if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3606 spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
3608 spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
3610 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
3615 AD1884_FIXUP_AMP_OVERRIDE,
3616 AD1884_FIXUP_HP_EAPD,
3619 static const struct hda_fixup ad1884_fixups[] = {
3620 [AD1884_FIXUP_AMP_OVERRIDE] = {
3621 .type = HDA_FIXUP_FUNC,
3622 .v.func = ad1884_fixup_amp_override,
3624 [AD1884_FIXUP_HP_EAPD] = {
3625 .type = HDA_FIXUP_FUNC,
3626 .v.func = ad1884_fixup_hp_eapd,
3628 .chain_id = AD1884_FIXUP_AMP_OVERRIDE,
3632 static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
3633 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
3638 static int ad1884_parse_auto_config(struct hda_codec *codec)
3640 struct ad198x_spec *spec;
3643 err = alloc_ad_spec(codec);
3648 spec->gen.mixer_nid = 0x20;
3649 spec->gen.beep_nid = 0x10;
3650 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3652 snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
3653 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
3655 err = ad198x_parse_auto_config(codec);
3658 err = ad1983_add_spdif_mux_ctl(codec);
3662 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
3667 snd_hda_gen_free(codec);
3671 #ifdef ENABLE_AD_STATIC_QUIRKS
3672 static int patch_ad1884_basic(struct hda_codec *codec)
3674 struct ad198x_spec *spec;
3677 err = alloc_ad_spec(codec);
3682 err = snd_hda_attach_beep_device(codec, 0x10);
3687 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3689 spec->multiout.max_channels = 2;
3690 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3691 spec->multiout.dac_nids = ad1884_dac_nids;
3692 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3693 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3694 spec->adc_nids = ad1884_adc_nids;
3695 spec->capsrc_nids = ad1884_capsrc_nids;
3696 spec->input_mux = &ad1884_capture_source;
3697 spec->num_mixers = 1;
3698 spec->mixers[0] = ad1884_base_mixers;
3699 spec->num_init_verbs = 1;
3700 spec->init_verbs[0] = ad1884_init_verbs;
3701 spec->spdif_route = 0;
3703 spec->loopback.amplist = ad1884_loopbacks;
3705 spec->vmaster_nid = 0x04;
3706 /* we need to cover all playback volumes */
3707 spec->slave_vols = ad1884_slave_vols;
3708 /* slaves may contain input volumes, so we can't raise to 0dB blindly */
3709 spec->avoid_init_slave_vol = 1;
3711 codec->patch_ops = ad198x_patch_ops;
3713 codec->no_trigger_sense = 1;
3714 codec->no_sticky_stream = 1;
3719 static int patch_ad1884(struct hda_codec *codec)
3723 board_config = snd_hda_check_board_config(codec, AD1884_MODELS,
3724 ad1884_models, NULL);
3725 if (board_config < 0) {
3726 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3728 board_config = AD1884_AUTO;
3731 if (board_config == AD1884_AUTO)
3732 return ad1884_parse_auto_config(codec);
3734 return patch_ad1884_basic(codec);
3736 #else /* ENABLE_AD_STATIC_QUIRKS */
3737 #define patch_ad1884 ad1884_parse_auto_config
3738 #endif /* ENABLE_AD_STATIC_QUIRKS */
3741 #ifdef ENABLE_AD_STATIC_QUIRKS
3743 * Lenovo Thinkpad T61/X61
3745 static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3749 { "Internal Mic", 0x1 },
3751 { "Dock Mic", 0x4 },
3757 * Dell Precision T3400
3759 static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3762 { "Front Mic", 0x0 },
3769 static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3770 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3771 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3772 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3773 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3774 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3775 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3776 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3777 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3778 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3779 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3780 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3781 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3782 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3783 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3784 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3785 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3786 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3787 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3788 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3791 /* The multiple "Capture Source" controls confuse alsamixer
3792 * So call somewhat different..
3794 /* .name = "Capture Source", */
3795 .name = "Input Source",
3797 .info = ad198x_mux_enum_info,
3798 .get = ad198x_mux_enum_get,
3799 .put = ad198x_mux_enum_put,
3801 /* SPDIF controls */
3802 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3805 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3806 /* identical with ad1983 */
3807 .info = ad1983_spdif_route_info,
3808 .get = ad1983_spdif_route_get,
3809 .put = ad1983_spdif_route_put,
3814 /* additional verbs */
3815 static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3816 /* Port-E (docking station mic) pin */
3817 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3818 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3819 /* docking mic boost */
3820 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3821 /* Analog PC Beeper - allow firmware/ACPI beeps */
3822 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3823 /* Analog mixer - docking mic; mute as default */
3824 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3825 /* enable EAPD bit */
3826 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3831 * Dell Precision T3400
3833 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3834 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3835 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3836 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3837 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3838 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3839 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3840 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3841 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3842 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3843 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3844 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3845 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3846 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3847 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3848 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3851 /* The multiple "Capture Source" controls confuse alsamixer
3852 * So call somewhat different..
3854 /* .name = "Capture Source", */
3855 .name = "Input Source",
3857 .info = ad198x_mux_enum_info,
3858 .get = ad198x_mux_enum_get,
3859 .put = ad198x_mux_enum_put,
3864 /* Digial MIC ADC NID 0x05 + 0x06 */
3865 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3866 struct hda_codec *codec,
3867 unsigned int stream_tag,
3868 unsigned int format,
3869 struct snd_pcm_substream *substream)
3871 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3872 stream_tag, 0, format);
3876 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3877 struct hda_codec *codec,
3878 struct snd_pcm_substream *substream)
3880 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3884 static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3890 .prepare = ad1984_pcm_dmic_prepare,
3891 .cleanup = ad1984_pcm_dmic_cleanup
3895 static int ad1984_build_pcms(struct hda_codec *codec)
3897 struct ad198x_spec *spec = codec->spec;
3898 struct hda_pcm *info;
3901 err = ad198x_build_pcms(codec);
3905 info = spec->pcm_rec + codec->num_pcms;
3907 info->name = "AD1984 Digital Mic";
3908 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3917 AD1984_DELL_DESKTOP,
3921 static const char * const ad1984_models[AD1984_MODELS] = {
3922 [AD1984_AUTO] = "auto",
3923 [AD1984_BASIC] = "basic",
3924 [AD1984_THINKPAD] = "thinkpad",
3925 [AD1984_DELL_DESKTOP] = "dell_desktop",
3928 static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3929 /* Lenovo Thinkpad T61/X61 */
3930 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3931 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3932 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3936 static int patch_ad1984(struct hda_codec *codec)
3938 struct ad198x_spec *spec;
3939 int board_config, err;
3941 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3942 ad1984_models, ad1984_cfg_tbl);
3943 if (board_config < 0) {
3944 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3946 board_config = AD1984_AUTO;
3949 if (board_config == AD1984_AUTO)
3950 return ad1884_parse_auto_config(codec);
3952 err = patch_ad1884_basic(codec);
3957 switch (board_config) {
3959 /* additional digital mics */
3960 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3961 codec->patch_ops.build_pcms = ad1984_build_pcms;
3963 case AD1984_THINKPAD:
3964 if (codec->subsystem_id == 0x17aa20fb) {
3965 /* Thinpad X300 does not have the ability to do SPDIF,
3966 or attach to docking station to use SPDIF */
3967 spec->multiout.dig_out_nid = 0;
3969 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3970 spec->input_mux = &ad1984_thinkpad_capture_source;
3971 spec->mixers[0] = ad1984_thinkpad_mixers;
3972 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3973 spec->analog_beep = 1;
3975 case AD1984_DELL_DESKTOP:
3976 spec->multiout.dig_out_nid = 0;
3977 spec->input_mux = &ad1984_dell_desktop_capture_source;
3978 spec->mixers[0] = ad1984_dell_desktop_mixers;
3983 #else /* ENABLE_AD_STATIC_QUIRKS */
3984 #define patch_ad1984 ad1884_parse_auto_config
3985 #endif /* ENABLE_AD_STATIC_QUIRKS */
3989 * AD1883 / AD1884A / AD1984A / AD1984B
3991 * port-B (0x14) - front mic-in
3992 * port-E (0x1c) - rear mic-in
3993 * port-F (0x16) - CD / ext out
3994 * port-C (0x15) - rear line-in
3995 * port-D (0x12) - rear line-out
3996 * port-A (0x11) - front hp-out
3998 * AD1984A = AD1884A + digital-mic
3999 * AD1883 = equivalent with AD1984A
4000 * AD1984B = AD1984A + extra SPDIF-out
4003 * We share the single DAC for both HP and line-outs (see AD1884/1984).
4006 #ifdef ENABLE_AD_STATIC_QUIRKS
4007 static const hda_nid_t ad1884a_dac_nids[1] = {
4011 #define ad1884a_adc_nids ad1884_adc_nids
4012 #define ad1884a_capsrc_nids ad1884_capsrc_nids
4014 #define AD1884A_SPDIF_OUT 0x02
4016 static const struct hda_input_mux ad1884a_capture_source = {
4019 { "Front Mic", 0x0 },
4027 static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
4028 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4029 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4030 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4031 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4032 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4033 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4034 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4035 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4036 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4037 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4038 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4039 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4040 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4041 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4042 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
4043 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
4044 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4045 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
4046 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4047 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4048 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4049 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4050 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4052 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4053 /* The multiple "Capture Source" controls confuse alsamixer
4054 * So call somewhat different..
4056 /* .name = "Capture Source", */
4057 .name = "Input Source",
4059 .info = ad198x_mux_enum_info,
4060 .get = ad198x_mux_enum_get,
4061 .put = ad198x_mux_enum_put,
4063 /* SPDIF controls */
4064 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4066 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4067 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4068 /* identical with ad1983 */
4069 .info = ad1983_spdif_route_info,
4070 .get = ad1983_spdif_route_get,
4071 .put = ad1983_spdif_route_put,
4077 * initialization verbs
4079 static const struct hda_verb ad1884a_init_verbs[] = {
4080 /* DACs; unmute as default */
4081 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4082 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4083 /* Port-A (HP) mixer - route only from analog mixer */
4084 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4085 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4087 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4088 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4089 /* Port-D (Line-out) mixer - route only from analog mixer */
4090 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4091 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4093 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4094 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4095 /* Mono-out mixer - route only from analog mixer */
4096 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4097 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4099 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4100 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4101 /* Port-B (front mic) pin */
4102 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4103 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4104 /* Port-C (rear line-in) pin */
4105 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4106 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4107 /* Port-E (rear mic) pin */
4108 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4109 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4110 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
4111 /* Port-F (CD) pin */
4112 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4113 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4114 /* Analog mixer; mute as default */
4115 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4116 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4117 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4118 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4119 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
4120 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4121 /* Analog Mix output amp */
4122 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4123 /* capture sources */
4124 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
4125 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4126 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4127 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4128 /* SPDIF output amp */
4129 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4134 static const struct hda_amp_list ad1884a_loopbacks[] = {
4135 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4136 { 0x20, HDA_INPUT, 1 }, /* Mic */
4137 { 0x20, HDA_INPUT, 2 }, /* CD */
4138 { 0x20, HDA_INPUT, 4 }, /* Docking */
4146 * Port A: Headphone jack
4148 * Port C: Internal MIC
4149 * Port D: Dock Line Out (if enabled)
4150 * Port E: Dock Line In (if enabled)
4151 * Port F: Internal speakers
4154 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
4155 struct snd_ctl_elem_value *ucontrol)
4157 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4158 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
4159 int mute = (!ucontrol->value.integer.value[0] &&
4160 !ucontrol->value.integer.value[1]);
4161 /* toggle GPIO1 according to the mute state */
4162 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
4167 static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
4168 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4170 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4171 .name = "Master Playback Switch",
4172 .subdevice = HDA_SUBDEV_AMP_FLAG,
4173 .info = snd_hda_mixer_amp_switch_info,
4174 .get = snd_hda_mixer_amp_switch_get,
4175 .put = ad1884a_mobile_master_sw_put,
4176 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4178 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4179 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4180 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4181 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4182 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4183 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4184 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4185 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4186 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4187 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4188 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4189 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4190 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4191 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4195 static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
4196 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4197 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4199 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4200 .name = "Master Playback Switch",
4201 .subdevice = HDA_SUBDEV_AMP_FLAG,
4202 .info = snd_hda_mixer_amp_switch_info,
4203 .get = snd_hda_mixer_amp_switch_get,
4204 .put = ad1884a_mobile_master_sw_put,
4205 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4207 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4208 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4209 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
4210 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
4211 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4212 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4216 /* mute internal speaker if HP is plugged */
4217 static void ad1884a_hp_automute(struct hda_codec *codec)
4219 unsigned int present;
4221 present = snd_hda_jack_detect(codec, 0x11);
4222 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4223 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4224 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4225 present ? 0x00 : 0x02);
4228 /* switch to external mic if plugged */
4229 static void ad1884a_hp_automic(struct hda_codec *codec)
4231 unsigned int present;
4233 present = snd_hda_jack_detect(codec, 0x14);
4234 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4238 #define AD1884A_HP_EVENT 0x37
4239 #define AD1884A_MIC_EVENT 0x36
4241 /* unsolicited event for HP jack sensing */
4242 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4244 switch (res >> 26) {
4245 case AD1884A_HP_EVENT:
4246 ad1884a_hp_automute(codec);
4248 case AD1884A_MIC_EVENT:
4249 ad1884a_hp_automic(codec);
4254 /* initialize jack-sensing, too */
4255 static int ad1884a_hp_init(struct hda_codec *codec)
4258 ad1884a_hp_automute(codec);
4259 ad1884a_hp_automic(codec);
4263 /* mute internal speaker if HP or docking HP is plugged */
4264 static void ad1884a_laptop_automute(struct hda_codec *codec)
4266 unsigned int present;
4268 present = snd_hda_jack_detect(codec, 0x11);
4270 present = snd_hda_jack_detect(codec, 0x12);
4271 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4272 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4273 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4274 present ? 0x00 : 0x02);
4277 /* switch to external mic if plugged */
4278 static void ad1884a_laptop_automic(struct hda_codec *codec)
4282 if (snd_hda_jack_detect(codec, 0x14))
4284 else if (snd_hda_jack_detect(codec, 0x1c))
4288 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4291 /* unsolicited event for HP jack sensing */
4292 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4295 switch (res >> 26) {
4296 case AD1884A_HP_EVENT:
4297 ad1884a_laptop_automute(codec);
4299 case AD1884A_MIC_EVENT:
4300 ad1884a_laptop_automic(codec);
4305 /* initialize jack-sensing, too */
4306 static int ad1884a_laptop_init(struct hda_codec *codec)
4309 ad1884a_laptop_automute(codec);
4310 ad1884a_laptop_automic(codec);
4314 /* additional verbs for laptop model */
4315 static const struct hda_verb ad1884a_laptop_verbs[] = {
4316 /* Port-A (HP) pin - always unmuted */
4317 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4318 /* Port-F (int speaker) mixer - route only from analog mixer */
4319 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4320 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4321 /* Port-F (int speaker) pin */
4322 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4323 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4324 /* required for compaq 6530s/6531s speaker output */
4325 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4326 /* Port-C pin - internal mic-in */
4327 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4328 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4329 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4330 /* Port-D (docking line-out) pin - default unmuted */
4331 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4333 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4334 /* unsolicited event for pin-sense */
4335 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4336 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4337 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4338 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4339 /* allow to touch GPIO1 (for mute control) */
4340 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4341 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4342 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4346 static const struct hda_verb ad1884a_mobile_verbs[] = {
4347 /* DACs; unmute as default */
4348 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4349 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4350 /* Port-A (HP) mixer - route only from analog mixer */
4351 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4352 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4354 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4355 /* Port-A (HP) pin - always unmuted */
4356 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4357 /* Port-B (mic jack) pin */
4358 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4359 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4360 /* Port-C (int mic) pin */
4361 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4362 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4363 /* Port-F (int speaker) mixer - route only from analog mixer */
4364 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4365 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4367 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4368 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4369 /* Analog mixer; mute as default */
4370 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4371 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4372 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4373 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4374 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4375 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4376 /* Analog Mix output amp */
4377 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4378 /* capture sources */
4379 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4380 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4381 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4382 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4383 /* unsolicited event for pin-sense */
4384 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4385 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4386 /* allow to touch GPIO1 (for mute control) */
4387 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4388 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4389 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4398 * 0x17 - built-in mic
4401 static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4403 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4405 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4407 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4408 /* unsolicited event for pin-sense */
4409 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4410 /* internal mic - dmic */
4411 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4412 /* set magic COEFs for dmic */
4413 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4414 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4418 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4419 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4420 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4421 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4422 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4423 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4424 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4425 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4426 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4427 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4428 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4431 .name = "Capture Source",
4432 .info = ad198x_mux_enum_info,
4433 .get = ad198x_mux_enum_get,
4434 .put = ad198x_mux_enum_put,
4439 static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4443 { "Internal Mic", 0x5 },
4448 /* mute internal speaker if HP is plugged */
4449 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4451 unsigned int present;
4453 present = snd_hda_jack_detect(codec, 0x11);
4454 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4455 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4458 /* unsolicited event for HP jack sensing */
4459 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4462 if ((res >> 26) != AD1884A_HP_EVENT)
4464 ad1984a_thinkpad_automute(codec);
4467 /* initialize jack-sensing, too */
4468 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4471 ad1984a_thinkpad_automute(codec);
4477 * 0x12 - HP/line-out
4478 * 0x13 - speaker (mono)
4482 static const struct hda_verb ad1984a_precision_verbs[] = {
4483 /* Unmute main output path */
4484 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4485 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4486 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4487 /* Analog mixer; mute as default */
4488 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4489 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4490 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4491 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4492 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4493 /* Select mic as input */
4494 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4495 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4496 /* Configure as mic */
4497 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4498 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4500 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4502 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4503 /* unsolicited event for pin-sense */
4504 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4508 static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4509 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4510 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4511 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4512 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4513 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4514 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4515 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4516 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4517 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4518 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4519 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4524 /* mute internal speaker if HP is plugged */
4525 static void ad1984a_precision_automute(struct hda_codec *codec)
4527 unsigned int present;
4529 present = snd_hda_jack_detect(codec, 0x12);
4530 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4531 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4535 /* unsolicited event for HP jack sensing */
4536 static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4539 if ((res >> 26) != AD1884A_HP_EVENT)
4541 ad1984a_precision_automute(codec);
4544 /* initialize jack-sensing, too */
4545 static int ad1984a_precision_init(struct hda_codec *codec)
4548 ad1984a_precision_automute(codec);
4555 * port-A (0x11) - front hp-out
4556 * port-B (0x14) - unused
4557 * port-C (0x15) - unused
4558 * port-D (0x12) - rear line out
4559 * port-E (0x1c) - front mic-in
4560 * port-F (0x16) - Internal speakers
4561 * digital-mic (0x17) - Internal mic
4564 static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4565 /* DACs; unmute as default */
4566 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4567 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4568 /* Port-A (HP) mixer - route only from analog mixer */
4569 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4570 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4572 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4573 /* Port-A (HP) pin - always unmuted */
4574 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4575 /* Port-E (int speaker) mixer - route only from analog mixer */
4576 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4578 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4579 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4580 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4581 /* Port-F (int speaker) mixer - route only from analog mixer */
4582 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4583 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4585 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4586 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4587 /* Analog mixer; mute as default */
4588 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4589 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4590 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4591 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4592 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4593 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4594 /* Analog Mix output amp */
4595 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4596 /* capture sources */
4597 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4598 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4599 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4600 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4601 /* unsolicited event for pin-sense */
4602 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4603 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4604 /* allow to touch GPIO1 (for mute control) */
4605 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4606 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4607 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4608 /* internal mic - dmic */
4609 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4610 /* set magic COEFs for dmic */
4611 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4612 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4616 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4617 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4618 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4620 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4621 .subdevice = HDA_SUBDEV_AMP_FLAG,
4622 .name = "Master Playback Switch",
4623 .info = snd_hda_mixer_amp_switch_info,
4624 .get = snd_hda_mixer_amp_switch_get,
4625 .put = ad1884a_mobile_master_sw_put,
4626 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4628 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4629 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4630 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4631 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4632 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4633 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4637 /* switch to external mic if plugged */
4638 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4640 if (snd_hda_jack_detect(codec, 0x1c))
4641 snd_hda_codec_write(codec, 0x0c, 0,
4642 AC_VERB_SET_CONNECT_SEL, 0x4);
4644 snd_hda_codec_write(codec, 0x0c, 0,
4645 AC_VERB_SET_CONNECT_SEL, 0x5);
4649 /* unsolicited event for HP jack sensing */
4650 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4653 switch (res >> 26) {
4654 case AD1884A_HP_EVENT:
4655 ad1884a_hp_automute(codec);
4657 case AD1884A_MIC_EVENT:
4658 ad1984a_touchsmart_automic(codec);
4663 /* initialize jack-sensing, too */
4664 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4667 ad1884a_hp_automute(codec);
4668 ad1984a_touchsmart_automic(codec);
4687 static const char * const ad1884a_models[AD1884A_MODELS] = {
4688 [AD1884A_AUTO] = "auto",
4689 [AD1884A_DESKTOP] = "desktop",
4690 [AD1884A_LAPTOP] = "laptop",
4691 [AD1884A_MOBILE] = "mobile",
4692 [AD1884A_THINKPAD] = "thinkpad",
4693 [AD1984A_TOUCHSMART] = "touchsmart",
4694 [AD1984A_PRECISION] = "precision",
4697 static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4698 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4699 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4700 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4701 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4702 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4703 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4704 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4705 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4706 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4707 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4708 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4712 static int patch_ad1884a(struct hda_codec *codec)
4714 struct ad198x_spec *spec;
4715 int err, board_config;
4717 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4720 if (board_config < 0) {
4721 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4723 board_config = AD1884A_AUTO;
4726 if (board_config == AD1884A_AUTO)
4727 return ad1884_parse_auto_config(codec);
4729 err = alloc_ad_spec(codec);
4734 err = snd_hda_attach_beep_device(codec, 0x10);
4739 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4741 spec->multiout.max_channels = 2;
4742 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4743 spec->multiout.dac_nids = ad1884a_dac_nids;
4744 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4745 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4746 spec->adc_nids = ad1884a_adc_nids;
4747 spec->capsrc_nids = ad1884a_capsrc_nids;
4748 spec->input_mux = &ad1884a_capture_source;
4749 spec->num_mixers = 1;
4750 spec->mixers[0] = ad1884a_base_mixers;
4751 spec->num_init_verbs = 1;
4752 spec->init_verbs[0] = ad1884a_init_verbs;
4753 spec->spdif_route = 0;
4755 spec->loopback.amplist = ad1884a_loopbacks;
4757 codec->patch_ops = ad198x_patch_ops;
4759 /* override some parameters */
4760 switch (board_config) {
4761 case AD1884A_LAPTOP:
4762 spec->mixers[0] = ad1884a_laptop_mixers;
4763 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4764 spec->multiout.dig_out_nid = 0;
4765 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4766 codec->patch_ops.init = ad1884a_laptop_init;
4767 /* set the upper-limit for mixer amp to 0dB for avoiding the
4768 * possible damage by overloading
4770 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4771 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4772 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4773 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4774 (1 << AC_AMPCAP_MUTE_SHIFT));
4776 case AD1884A_MOBILE:
4777 spec->mixers[0] = ad1884a_mobile_mixers;
4778 spec->init_verbs[0] = ad1884a_mobile_verbs;
4779 spec->multiout.dig_out_nid = 0;
4780 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4781 codec->patch_ops.init = ad1884a_hp_init;
4782 /* set the upper-limit for mixer amp to 0dB for avoiding the
4783 * possible damage by overloading
4785 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4786 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4787 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4788 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4789 (1 << AC_AMPCAP_MUTE_SHIFT));
4791 case AD1884A_THINKPAD:
4792 spec->mixers[0] = ad1984a_thinkpad_mixers;
4793 spec->init_verbs[spec->num_init_verbs++] =
4794 ad1984a_thinkpad_verbs;
4795 spec->multiout.dig_out_nid = 0;
4796 spec->input_mux = &ad1984a_thinkpad_capture_source;
4797 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4798 codec->patch_ops.init = ad1984a_thinkpad_init;
4800 case AD1984A_PRECISION:
4801 spec->mixers[0] = ad1984a_precision_mixers;
4802 spec->init_verbs[spec->num_init_verbs++] =
4803 ad1984a_precision_verbs;
4804 spec->multiout.dig_out_nid = 0;
4805 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4806 codec->patch_ops.init = ad1984a_precision_init;
4808 case AD1984A_TOUCHSMART:
4809 spec->mixers[0] = ad1984a_touchsmart_mixers;
4810 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4811 spec->multiout.dig_out_nid = 0;
4812 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4813 codec->patch_ops.init = ad1984a_touchsmart_init;
4814 /* set the upper-limit for mixer amp to 0dB for avoiding the
4815 * possible damage by overloading
4817 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4818 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4819 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4820 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4821 (1 << AC_AMPCAP_MUTE_SHIFT));
4825 codec->no_trigger_sense = 1;
4826 codec->no_sticky_stream = 1;
4830 #else /* ENABLE_AD_STATIC_QUIRKS */
4831 #define patch_ad1884a ad1884_parse_auto_config
4832 #endif /* ENABLE_AD_STATIC_QUIRKS */
4838 * port-A - front hp-out
4839 * port-B - front mic-in
4840 * port-C - rear line-in, shared surr-out (3stack)
4841 * port-D - rear line-out
4842 * port-E - rear mic-in, shared clfe-out (3stack)
4843 * port-F - rear surr-out (6stack)
4844 * port-G - rear clfe-out (6stack)
4847 #ifdef ENABLE_AD_STATIC_QUIRKS
4848 static const hda_nid_t ad1882_dac_nids[3] = {
4852 static const hda_nid_t ad1882_adc_nids[2] = {
4856 static const hda_nid_t ad1882_capsrc_nids[2] = {
4860 #define AD1882_SPDIF_OUT 0x02
4862 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4863 static const struct hda_input_mux ad1882_capture_source = {
4866 { "Front Mic", 0x1 },
4874 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4875 static const struct hda_input_mux ad1882a_capture_source = {
4878 { "Front Mic", 0x1 },
4881 { "Digital Mic", 0x06 },
4886 static const struct snd_kcontrol_new ad1882_base_mixers[] = {
4887 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4888 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4889 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4890 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4891 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4892 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4893 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4894 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4896 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
4897 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
4898 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
4899 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4900 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4901 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4902 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4904 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4905 /* The multiple "Capture Source" controls confuse alsamixer
4906 * So call somewhat different..
4908 /* .name = "Capture Source", */
4909 .name = "Input Source",
4911 .info = ad198x_mux_enum_info,
4912 .get = ad198x_mux_enum_get,
4913 .put = ad198x_mux_enum_put,
4915 /* SPDIF controls */
4916 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4918 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4919 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4920 /* identical with ad1983 */
4921 .info = ad1983_spdif_route_info,
4922 .get = ad1983_spdif_route_get,
4923 .put = ad1983_spdif_route_put,
4928 static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4929 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4930 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4931 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4932 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4933 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4934 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4935 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4936 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4940 static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4941 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4942 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4943 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4944 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4945 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4946 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4947 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4948 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4949 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
4953 static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4954 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4955 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4956 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4958 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4959 .name = "Channel Mode",
4960 .info = ad198x_ch_mode_info,
4961 .get = ad198x_ch_mode_get,
4962 .put = ad198x_ch_mode_put,
4967 /* simple auto-mute control for AD1882 3-stack board */
4968 #define AD1882_HP_EVENT 0x01
4970 static void ad1882_3stack_automute(struct hda_codec *codec)
4972 bool mute = snd_hda_jack_detect(codec, 0x11);
4973 snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4974 mute ? 0 : PIN_OUT);
4977 static int ad1882_3stack_automute_init(struct hda_codec *codec)
4980 ad1882_3stack_automute(codec);
4984 static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res)
4986 switch (res >> 26) {
4987 case AD1882_HP_EVENT:
4988 ad1882_3stack_automute(codec);
4993 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4994 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4995 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4996 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
5000 static const struct hda_verb ad1882_ch2_init[] = {
5001 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5002 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5003 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5004 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5005 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5006 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5010 static const struct hda_verb ad1882_ch4_init[] = {
5011 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5012 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5013 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5014 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5015 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5016 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5020 static const struct hda_verb ad1882_ch6_init[] = {
5021 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5022 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5023 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5024 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5025 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5026 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5030 static const struct hda_channel_mode ad1882_modes[3] = {
5031 { 2, ad1882_ch2_init },
5032 { 4, ad1882_ch4_init },
5033 { 6, ad1882_ch6_init },
5037 * initialization verbs
5039 static const struct hda_verb ad1882_init_verbs[] = {
5040 /* DACs; mute as default */
5041 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5042 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5043 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5044 /* Port-A (HP) mixer */
5045 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5046 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5048 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5049 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5050 /* HP selector - select DAC2 */
5051 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
5052 /* Port-D (Line-out) mixer */
5053 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5054 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5056 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5057 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5058 /* Mono-out mixer */
5059 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5060 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5062 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5063 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5064 /* Port-B (front mic) pin */
5065 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5066 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5067 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5068 /* Port-C (line-in) pin */
5069 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5070 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5071 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5072 /* Port-C mixer - mute as input */
5073 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5074 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5075 /* Port-E (mic-in) pin */
5076 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5077 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5078 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5079 /* Port-E mixer - mute as input */
5080 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5081 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5082 /* Port-F (surround) */
5083 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5084 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5086 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5087 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5088 /* Analog mixer; mute as default */
5089 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
5090 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5091 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5092 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5093 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5094 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5095 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
5096 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
5097 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
5098 /* Analog Mix output amp */
5099 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
5100 /* SPDIF output selector */
5101 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
5102 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
5103 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
5107 static const struct hda_verb ad1882_3stack_automute_verbs[] = {
5108 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT},
5113 static const struct hda_amp_list ad1882_loopbacks[] = {
5114 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
5115 { 0x20, HDA_INPUT, 1 }, /* Mic */
5116 { 0x20, HDA_INPUT, 4 }, /* Line */
5117 { 0x20, HDA_INPUT, 6 }, /* CD */
5127 AD1882_3STACK_AUTOMUTE,
5131 static const char * const ad1882_models[AD1986A_MODELS] = {
5132 [AD1882_AUTO] = "auto",
5133 [AD1882_3STACK] = "3stack",
5134 [AD1882_6STACK] = "6stack",
5135 [AD1882_3STACK_AUTOMUTE] = "3stack-automute",
5137 #endif /* ENABLE_AD_STATIC_QUIRKS */
5139 static int ad1882_parse_auto_config(struct hda_codec *codec)
5141 struct ad198x_spec *spec;
5144 err = alloc_ad_spec(codec);
5149 spec->gen.mixer_nid = 0x20;
5150 spec->gen.mixer_merge_nid = 0x21;
5151 spec->gen.beep_nid = 0x10;
5152 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
5153 err = ad198x_parse_auto_config(codec);
5156 err = ad1988_add_spdif_mux_ctl(codec);
5162 snd_hda_gen_free(codec);
5166 #ifdef ENABLE_AD_STATIC_QUIRKS
5167 static int patch_ad1882(struct hda_codec *codec)
5169 struct ad198x_spec *spec;
5170 int err, board_config;
5172 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
5173 ad1882_models, NULL);
5174 if (board_config < 0) {
5175 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5177 board_config = AD1882_AUTO;
5180 if (board_config == AD1882_AUTO)
5181 return ad1882_parse_auto_config(codec);
5183 err = alloc_ad_spec(codec);
5188 err = snd_hda_attach_beep_device(codec, 0x10);
5193 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
5195 spec->multiout.max_channels = 6;
5196 spec->multiout.num_dacs = 3;
5197 spec->multiout.dac_nids = ad1882_dac_nids;
5198 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
5199 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
5200 spec->adc_nids = ad1882_adc_nids;
5201 spec->capsrc_nids = ad1882_capsrc_nids;
5202 if (codec->vendor_id == 0x11d41882)
5203 spec->input_mux = &ad1882_capture_source;
5205 spec->input_mux = &ad1882a_capture_source;
5206 spec->num_mixers = 2;
5207 spec->mixers[0] = ad1882_base_mixers;
5208 if (codec->vendor_id == 0x11d41882)
5209 spec->mixers[1] = ad1882_loopback_mixers;
5211 spec->mixers[1] = ad1882a_loopback_mixers;
5212 spec->num_init_verbs = 1;
5213 spec->init_verbs[0] = ad1882_init_verbs;
5214 spec->spdif_route = 0;
5216 spec->loopback.amplist = ad1882_loopbacks;
5218 spec->vmaster_nid = 0x04;
5220 codec->patch_ops = ad198x_patch_ops;
5222 /* override some parameters */
5223 switch (board_config) {
5226 case AD1882_3STACK_AUTOMUTE:
5227 spec->num_mixers = 3;
5228 spec->mixers[2] = ad1882_3stack_mixers;
5229 spec->channel_mode = ad1882_modes;
5230 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
5231 spec->need_dac_fix = 1;
5232 spec->multiout.max_channels = 2;
5233 spec->multiout.num_dacs = 1;
5234 if (board_config != AD1882_3STACK) {
5235 spec->init_verbs[spec->num_init_verbs++] =
5236 ad1882_3stack_automute_verbs;
5237 codec->patch_ops.unsol_event = ad1882_3stack_unsol_event;
5238 codec->patch_ops.init = ad1882_3stack_automute_init;
5242 spec->num_mixers = 3;
5243 spec->mixers[2] = ad1882_6stack_mixers;
5247 codec->no_trigger_sense = 1;
5248 codec->no_sticky_stream = 1;
5252 #else /* ENABLE_AD_STATIC_QUIRKS */
5253 #define patch_ad1882 ad1882_parse_auto_config
5254 #endif /* ENABLE_AD_STATIC_QUIRKS */
5260 static const struct hda_codec_preset snd_hda_preset_analog[] = {
5261 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
5262 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
5263 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
5264 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
5265 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
5266 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
5267 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
5268 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
5269 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
5270 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
5271 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
5272 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
5273 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
5274 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
5275 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
5279 MODULE_ALIAS("snd-hda-codec-id:11d4*");
5281 MODULE_LICENSE("GPL");
5282 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
5284 static struct hda_codec_preset_list analog_list = {
5285 .preset = snd_hda_preset_analog,
5286 .owner = THIS_MODULE,
5289 static int __init patch_analog_init(void)
5291 return snd_hda_add_codec_preset(&analog_list);
5294 static void __exit patch_analog_exit(void)
5296 snd_hda_delete_codec_preset(&analog_list);
5299 module_init(patch_analog_init)
5300 module_exit(patch_analog_exit)