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/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 const struct snd_kcontrol_new *mixers[6];
35 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb *init_verbs[6]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs;
42 struct hda_multi_out multiout; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd;
47 unsigned int need_dac_fix;
49 const hda_nid_t *alt_dac_nid;
50 const struct hda_pcm_stream *stream_analog_alt_playback;
52 int num_active_streams;
55 unsigned int num_adc_nids;
56 const hda_nid_t *adc_nids;
57 hda_nid_t dig_in_nid; /* digital-in NID; optional */
60 const struct hda_input_mux *input_mux;
61 const hda_nid_t *capsrc_nids;
62 unsigned int cur_mux[3];
65 const struct hda_channel_mode *channel_mode;
69 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
71 unsigned int spdif_route;
73 /* dynamic controls, init_verbs and input_mux */
74 struct auto_pin_cfg autocfg;
75 struct snd_array kctls;
76 struct hda_input_mux private_imux;
77 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
79 unsigned int jack_present: 1;
80 unsigned int inv_jack_detect: 1;/* inverted jack-detection */
81 unsigned int inv_eapd: 1; /* inverted EAPD implementation */
82 unsigned int analog_beep: 1; /* analog beep input present */
84 #ifdef CONFIG_SND_HDA_POWER_SAVE
85 struct hda_loopback_check loopback;
87 /* for virtual master */
88 hda_nid_t vmaster_nid;
89 const char * const *slave_vols;
90 const char * const *slave_sws;
94 * input MUX handling (common part)
96 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
98 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
99 struct ad198x_spec *spec = codec->spec;
101 return snd_hda_input_mux_info(spec->input_mux, uinfo);
104 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
106 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
107 struct ad198x_spec *spec = codec->spec;
108 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
110 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
114 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
116 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
117 struct ad198x_spec *spec = codec->spec;
118 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
120 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
121 spec->capsrc_nids[adc_idx],
122 &spec->cur_mux[adc_idx]);
126 * initialization (common callbacks)
128 static int ad198x_init(struct hda_codec *codec)
130 struct ad198x_spec *spec = codec->spec;
133 for (i = 0; i < spec->num_init_verbs; i++)
134 snd_hda_sequence_write(codec, spec->init_verbs[i]);
138 static const char * const ad_slave_vols[] = {
139 "Front Playback Volume",
140 "Surround Playback Volume",
141 "Center Playback Volume",
142 "LFE Playback Volume",
143 "Side Playback Volume",
144 "Headphone Playback Volume",
145 "Mono Playback Volume",
146 "Speaker Playback Volume",
147 "IEC958 Playback Volume",
151 static const char * const ad_slave_sws[] = {
152 "Front Playback Switch",
153 "Surround Playback Switch",
154 "Center Playback Switch",
155 "LFE Playback Switch",
156 "Side Playback Switch",
157 "Headphone Playback Switch",
158 "Mono Playback Switch",
159 "Speaker Playback Switch",
160 "IEC958 Playback Switch",
164 static const char * const ad1988_6stack_fp_slave_vols[] = {
165 "Front Playback Volume",
166 "Surround Playback Volume",
167 "Center Playback Volume",
168 "LFE Playback Volume",
169 "Side Playback Volume",
170 "IEC958 Playback Volume",
174 static const char * const ad1988_6stack_fp_slave_sws[] = {
175 "Front Playback Switch",
176 "Surround Playback Switch",
177 "Center Playback Switch",
178 "LFE Playback Switch",
179 "Side Playback Switch",
180 "IEC958 Playback Switch",
183 static void ad198x_free_kctls(struct hda_codec *codec);
185 #ifdef CONFIG_SND_HDA_INPUT_BEEP
186 /* additional beep mixers; the actual parameters are overwritten at build */
187 static const struct snd_kcontrol_new ad_beep_mixer[] = {
188 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
189 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
193 static const struct snd_kcontrol_new ad_beep2_mixer[] = {
194 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
195 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
199 #define set_beep_amp(spec, nid, idx, dir) \
200 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
202 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
205 static int ad198x_build_controls(struct hda_codec *codec)
207 struct ad198x_spec *spec = codec->spec;
208 struct snd_kcontrol *kctl;
212 for (i = 0; i < spec->num_mixers; i++) {
213 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
217 if (spec->multiout.dig_out_nid) {
218 err = snd_hda_create_spdif_out_ctls(codec,
219 spec->multiout.dig_out_nid,
220 spec->multiout.dig_out_nid);
223 err = snd_hda_create_spdif_share_sw(codec,
227 spec->multiout.share_spdif = 1;
229 if (spec->dig_in_nid) {
230 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
235 /* create beep controls if needed */
236 #ifdef CONFIG_SND_HDA_INPUT_BEEP
237 if (spec->beep_amp) {
238 const struct snd_kcontrol_new *knew;
239 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
240 for ( ; knew->name; knew++) {
241 struct snd_kcontrol *kctl;
242 kctl = snd_ctl_new1(knew, codec);
245 kctl->private_value = spec->beep_amp;
246 err = snd_hda_ctl_add(codec, 0, kctl);
253 /* if we have no master control, let's create it */
254 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
255 unsigned int vmaster_tlv[4];
256 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
257 HDA_OUTPUT, vmaster_tlv);
258 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
261 spec->slave_vols : ad_slave_vols));
265 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
266 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
269 spec->slave_sws : ad_slave_sws));
274 ad198x_free_kctls(codec); /* no longer needed */
276 /* assign Capture Source enums to NID */
277 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
279 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
280 for (i = 0; kctl && i < kctl->count; i++) {
281 err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
286 /* assign IEC958 enums to NID */
287 kctl = snd_hda_find_mixer_ctl(codec,
288 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
290 err = snd_hda_add_nid(codec, kctl, 0,
291 spec->multiout.dig_out_nid);
299 #ifdef CONFIG_SND_HDA_POWER_SAVE
300 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
302 struct ad198x_spec *spec = codec->spec;
303 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
307 static void activate_ctl(struct hda_codec *codec, const char *name, int active)
309 struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
311 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
312 ctl->vd[0].access |= active ? 0 :
313 SNDRV_CTL_ELEM_ACCESS_INACTIVE;
314 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;
315 ctl->vd[0].access |= active ?
316 SNDRV_CTL_ELEM_ACCESS_WRITE : 0;
317 snd_ctl_notify(codec->bus->card,
318 SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
322 static void set_stream_active(struct hda_codec *codec, bool active)
324 struct ad198x_spec *spec = codec->spec;
326 spec->num_active_streams++;
328 spec->num_active_streams--;
329 activate_ctl(codec, "Independent HP", spec->num_active_streams == 0);
332 static int ad1988_independent_hp_info(struct snd_kcontrol *kcontrol,
333 struct snd_ctl_elem_info *uinfo)
335 static const char * const texts[] = { "OFF", "ON", NULL};
337 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
339 uinfo->value.enumerated.items = 2;
340 index = uinfo->value.enumerated.item;
343 strcpy(uinfo->value.enumerated.name, texts[index]);
347 static int ad1988_independent_hp_get(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
350 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
351 struct ad198x_spec *spec = codec->spec;
352 ucontrol->value.enumerated.item[0] = spec->independent_hp;
356 static int ad1988_independent_hp_put(struct snd_kcontrol *kcontrol,
357 struct snd_ctl_elem_value *ucontrol)
359 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
360 struct ad198x_spec *spec = codec->spec;
361 unsigned int select = ucontrol->value.enumerated.item[0];
362 if (spec->independent_hp != select) {
363 spec->independent_hp = select;
364 if (spec->independent_hp)
365 spec->multiout.hp_nid = 0;
367 spec->multiout.hp_nid = spec->alt_dac_nid[0];
374 * Analog playback callbacks
376 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
377 struct hda_codec *codec,
378 struct snd_pcm_substream *substream)
380 struct ad198x_spec *spec = codec->spec;
382 set_stream_active(codec, true);
383 err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
386 set_stream_active(codec, false);
392 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
393 struct hda_codec *codec,
394 unsigned int stream_tag,
396 struct snd_pcm_substream *substream)
398 struct ad198x_spec *spec = codec->spec;
399 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
403 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
404 struct hda_codec *codec,
405 struct snd_pcm_substream *substream)
407 struct ad198x_spec *spec = codec->spec;
408 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
411 static int ad198x_playback_pcm_close(struct hda_pcm_stream *hinfo,
412 struct hda_codec *codec,
413 struct snd_pcm_substream *substream)
415 set_stream_active(codec, false);
419 static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
420 struct hda_codec *codec,
421 struct snd_pcm_substream *substream)
423 struct ad198x_spec *spec = codec->spec;
424 if (!spec->independent_hp)
426 set_stream_active(codec, true);
430 static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
431 struct hda_codec *codec,
432 struct snd_pcm_substream *substream)
434 set_stream_active(codec, false);
438 static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
443 .open = ad1988_alt_playback_pcm_open,
444 .close = ad1988_alt_playback_pcm_close
451 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
452 struct hda_codec *codec,
453 struct snd_pcm_substream *substream)
455 struct ad198x_spec *spec = codec->spec;
456 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
459 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
460 struct hda_codec *codec,
461 struct snd_pcm_substream *substream)
463 struct ad198x_spec *spec = codec->spec;
464 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
467 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
468 struct hda_codec *codec,
469 unsigned int stream_tag,
471 struct snd_pcm_substream *substream)
473 struct ad198x_spec *spec = codec->spec;
474 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
478 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
479 struct hda_codec *codec,
480 struct snd_pcm_substream *substream)
482 struct ad198x_spec *spec = codec->spec;
483 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
489 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
490 struct hda_codec *codec,
491 unsigned int stream_tag,
493 struct snd_pcm_substream *substream)
495 struct ad198x_spec *spec = codec->spec;
496 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
497 stream_tag, 0, format);
501 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
502 struct hda_codec *codec,
503 struct snd_pcm_substream *substream)
505 struct ad198x_spec *spec = codec->spec;
506 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
512 static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
515 .channels_max = 6, /* changed later */
516 .nid = 0, /* fill later */
518 .open = ad198x_playback_pcm_open,
519 .prepare = ad198x_playback_pcm_prepare,
520 .cleanup = ad198x_playback_pcm_cleanup,
521 .close = ad198x_playback_pcm_close
525 static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
529 .nid = 0, /* fill later */
531 .prepare = ad198x_capture_pcm_prepare,
532 .cleanup = ad198x_capture_pcm_cleanup
536 static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
540 .nid = 0, /* fill later */
542 .open = ad198x_dig_playback_pcm_open,
543 .close = ad198x_dig_playback_pcm_close,
544 .prepare = ad198x_dig_playback_pcm_prepare,
545 .cleanup = ad198x_dig_playback_pcm_cleanup
549 static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
553 /* NID is set in alc_build_pcms */
556 static int ad198x_build_pcms(struct hda_codec *codec)
558 struct ad198x_spec *spec = codec->spec;
559 struct hda_pcm *info = spec->pcm_rec;
562 codec->pcm_info = info;
564 info->name = "AD198x Analog";
565 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
566 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
567 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
568 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
569 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
570 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
572 if (spec->multiout.dig_out_nid) {
575 info->name = "AD198x Digital";
576 info->pcm_type = HDA_PCM_TYPE_SPDIF;
577 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
578 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
579 if (spec->dig_in_nid) {
580 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
581 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
585 if (spec->alt_dac_nid && spec->stream_analog_alt_playback) {
587 info = spec->pcm_rec + 2;
588 info->name = "AD198x Headphone";
589 info->pcm_type = HDA_PCM_TYPE_AUDIO;
590 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
591 *spec->stream_analog_alt_playback;
592 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
593 spec->alt_dac_nid[0];
599 static void ad198x_free_kctls(struct hda_codec *codec)
601 struct ad198x_spec *spec = codec->spec;
603 if (spec->kctls.list) {
604 struct snd_kcontrol_new *kctl = spec->kctls.list;
606 for (i = 0; i < spec->kctls.used; i++)
609 snd_array_free(&spec->kctls);
612 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
615 struct ad198x_spec *spec = codec->spec;
616 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
617 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
618 !spec->inv_eapd ? 0x00 : 0x02);
619 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
620 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
621 !spec->inv_eapd ? 0x00 : 0x02);
624 static void ad198x_power_eapd(struct hda_codec *codec)
626 /* We currently only handle front, HP */
627 switch (codec->vendor_id) {
640 ad198x_power_eapd_write(codec, 0x12, 0x11);
644 ad198x_power_eapd_write(codec, 0x05, 0x06);
647 ad198x_power_eapd_write(codec, 0x1b, 0x1a);
652 static void ad198x_shutup(struct hda_codec *codec)
654 snd_hda_shutup_pins(codec);
655 ad198x_power_eapd(codec);
658 static void ad198x_free(struct hda_codec *codec)
660 struct ad198x_spec *spec = codec->spec;
665 ad198x_shutup(codec);
666 ad198x_free_kctls(codec);
668 snd_hda_detach_beep_device(codec);
672 static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
674 ad198x_shutup(codec);
679 static const struct hda_codec_ops ad198x_patch_ops = {
680 .build_controls = ad198x_build_controls,
681 .build_pcms = ad198x_build_pcms,
684 #ifdef CONFIG_SND_HDA_POWER_SAVE
685 .check_power_status = ad198x_check_power_status,
688 .suspend = ad198x_suspend,
690 .reboot_notify = ad198x_shutup,
696 * the private value = nid
698 #define ad198x_eapd_info snd_ctl_boolean_mono_info
700 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
701 struct snd_ctl_elem_value *ucontrol)
703 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
704 struct ad198x_spec *spec = codec->spec;
706 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
708 ucontrol->value.integer.value[0] = spec->cur_eapd;
712 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
713 struct snd_ctl_elem_value *ucontrol)
715 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
716 struct ad198x_spec *spec = codec->spec;
717 hda_nid_t nid = kcontrol->private_value & 0xff;
719 eapd = !!ucontrol->value.integer.value[0];
722 if (eapd == spec->cur_eapd)
724 spec->cur_eapd = eapd;
725 snd_hda_codec_write_cache(codec, nid,
726 0, AC_VERB_SET_EAPD_BTLENABLE,
731 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
732 struct snd_ctl_elem_info *uinfo);
733 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
734 struct snd_ctl_elem_value *ucontrol);
735 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
736 struct snd_ctl_elem_value *ucontrol);
743 #define AD1986A_SPDIF_OUT 0x02
744 #define AD1986A_FRONT_DAC 0x03
745 #define AD1986A_SURR_DAC 0x04
746 #define AD1986A_CLFE_DAC 0x05
747 #define AD1986A_ADC 0x06
749 static const hda_nid_t ad1986a_dac_nids[3] = {
750 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
752 static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
753 static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
755 static const struct hda_input_mux ad1986a_capture_source = {
769 static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
770 .ops = &snd_hda_bind_vol,
772 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
773 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
774 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
779 static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
780 .ops = &snd_hda_bind_sw,
782 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
783 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
784 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
792 static const struct snd_kcontrol_new ad1986a_mixers[] = {
794 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
796 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
797 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
798 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
799 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
800 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
801 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
802 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
803 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
804 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
805 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
806 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
807 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
808 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
809 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
810 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
811 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
812 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
813 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
814 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
815 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
816 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
817 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
818 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
819 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
820 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
822 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
823 .name = "Capture Source",
824 .info = ad198x_mux_enum_info,
825 .get = ad198x_mux_enum_get,
826 .put = ad198x_mux_enum_put,
828 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
832 /* additional mixers for 3stack mode */
833 static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
835 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
836 .name = "Channel Mode",
837 .info = ad198x_ch_mode_info,
838 .get = ad198x_ch_mode_get,
839 .put = ad198x_ch_mode_put,
844 /* laptop model - 2ch only */
845 static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
847 /* master controls both pins 0x1a and 0x1b */
848 static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
849 .ops = &snd_hda_bind_vol,
851 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
852 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
857 static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
858 .ops = &snd_hda_bind_sw,
860 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
861 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
866 static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
867 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
868 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
869 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
870 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
871 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
872 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
873 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
874 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
875 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
876 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
877 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
878 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
879 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
881 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
882 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
883 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
884 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
886 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
887 .name = "Capture Source",
888 .info = ad198x_mux_enum_info,
889 .get = ad198x_mux_enum_get,
890 .put = ad198x_mux_enum_put,
895 /* laptop-eapd model - 2ch only */
897 static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
901 { "Internal Mic", 0x4 },
906 static const struct hda_input_mux ad1986a_automic_capture_source = {
914 static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
915 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
916 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
920 static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
921 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
922 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
923 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
924 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
925 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
926 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
927 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
929 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
930 .name = "Capture Source",
931 .info = ad198x_mux_enum_info,
932 .get = ad198x_mux_enum_get,
933 .put = ad198x_mux_enum_put,
936 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
937 .name = "External Amplifier",
938 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
939 .info = ad198x_eapd_info,
940 .get = ad198x_eapd_get,
941 .put = ad198x_eapd_put,
942 .private_value = 0x1b, /* port-D */
947 static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
948 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
949 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
953 /* re-connect the mic boost input according to the jack sensing */
954 static void ad1986a_automic(struct hda_codec *codec)
956 unsigned int present;
957 present = snd_hda_jack_detect(codec, 0x1f);
958 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
959 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
963 #define AD1986A_MIC_EVENT 0x36
965 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
968 if ((res >> 26) != AD1986A_MIC_EVENT)
970 ad1986a_automic(codec);
973 static int ad1986a_automic_init(struct hda_codec *codec)
976 ad1986a_automic(codec);
980 /* laptop-automute - 2ch only */
982 static void ad1986a_update_hp(struct hda_codec *codec)
984 struct ad198x_spec *spec = codec->spec;
987 if (spec->jack_present)
988 mute = HDA_AMP_MUTE; /* mute internal speaker */
990 /* unmute internal speaker if necessary */
991 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
992 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
996 static void ad1986a_hp_automute(struct hda_codec *codec)
998 struct ad198x_spec *spec = codec->spec;
1000 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
1001 if (spec->inv_jack_detect)
1002 spec->jack_present = !spec->jack_present;
1003 ad1986a_update_hp(codec);
1006 #define AD1986A_HP_EVENT 0x37
1008 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
1010 if ((res >> 26) != AD1986A_HP_EVENT)
1012 ad1986a_hp_automute(codec);
1015 static int ad1986a_hp_init(struct hda_codec *codec)
1018 ad1986a_hp_automute(codec);
1022 /* bind hp and internal speaker mute (with plug check) */
1023 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1024 struct snd_ctl_elem_value *ucontrol)
1026 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1027 long *valp = ucontrol->value.integer.value;
1030 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
1032 valp[0] ? 0 : HDA_AMP_MUTE);
1033 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
1035 valp[1] ? 0 : HDA_AMP_MUTE);
1037 ad1986a_update_hp(codec);
1041 static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
1042 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
1044 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1045 .name = "Master Playback Switch",
1046 .subdevice = HDA_SUBDEV_AMP_FLAG,
1047 .info = snd_hda_mixer_amp_switch_info,
1048 .get = snd_hda_mixer_amp_switch_get,
1049 .put = ad1986a_hp_master_sw_put,
1050 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
1057 * initialization verbs
1059 static const struct hda_verb ad1986a_init_verbs[] = {
1060 /* Front, Surround, CLFE DAC; mute as default */
1061 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1062 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1063 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1065 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1066 /* HP, Line-Out, Surround, CLFE selectors */
1067 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
1068 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
1069 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1070 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1072 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
1073 /* Mic selector: Mic 1/2 pin */
1074 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1075 /* Line-in selector: Line-in */
1076 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
1078 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
1079 /* Record selector: mic */
1080 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
1081 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
1082 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1083 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1084 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1085 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1086 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1088 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
1089 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
1090 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1091 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1092 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1093 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1094 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1096 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1097 /* Front, Surround, CLFE Pins */
1098 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1099 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1100 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1102 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1104 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1105 /* Line, Aux, CD, Beep-In Pin */
1106 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1107 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1108 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1109 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1110 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1114 static const struct hda_verb ad1986a_ch2_init[] = {
1115 /* Surround out -> Line In */
1116 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1117 /* Line-in selectors */
1118 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
1119 /* CLFE -> Mic in */
1120 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1121 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1122 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1126 static const struct hda_verb ad1986a_ch4_init[] = {
1127 /* Surround out -> Surround */
1128 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1129 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1130 /* CLFE -> Mic in */
1131 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1132 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1136 static const struct hda_verb ad1986a_ch6_init[] = {
1137 /* Surround out -> Surround out */
1138 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1139 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1141 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1142 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1146 static const struct hda_channel_mode ad1986a_modes[3] = {
1147 { 2, ad1986a_ch2_init },
1148 { 4, ad1986a_ch4_init },
1149 { 6, ad1986a_ch6_init },
1152 /* eapd initialization */
1153 static const struct hda_verb ad1986a_eapd_init_verbs[] = {
1154 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1158 static const struct hda_verb ad1986a_automic_verbs[] = {
1159 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1160 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1161 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1162 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1163 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1167 /* Ultra initialization */
1168 static const struct hda_verb ad1986a_ultra_init[] = {
1169 /* eapd initialization */
1170 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1171 /* CLFE -> Mic in */
1172 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1173 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1174 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1178 /* pin sensing on HP jack */
1179 static const struct hda_verb ad1986a_hp_init_verbs[] = {
1180 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1184 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1187 switch (res >> 26) {
1188 case AD1986A_HP_EVENT:
1189 ad1986a_hp_automute(codec);
1191 case AD1986A_MIC_EVENT:
1192 ad1986a_automic(codec);
1197 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1200 ad1986a_hp_automute(codec);
1201 ad1986a_automic(codec);
1211 AD1986A_LAPTOP_EAPD,
1212 AD1986A_LAPTOP_AUTOMUTE,
1215 AD1986A_SAMSUNG_P50,
1219 static const char * const ad1986a_models[AD1986A_MODELS] = {
1220 [AD1986A_6STACK] = "6stack",
1221 [AD1986A_3STACK] = "3stack",
1222 [AD1986A_LAPTOP] = "laptop",
1223 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1224 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1225 [AD1986A_ULTRA] = "ultra",
1226 [AD1986A_SAMSUNG] = "samsung",
1227 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1230 static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1231 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1232 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1233 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1234 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1235 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1236 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1237 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1238 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1239 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1240 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1241 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1242 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1243 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1244 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1245 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1246 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1247 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1248 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1249 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1250 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1251 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1252 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1253 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1254 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1255 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1256 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1257 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1261 #ifdef CONFIG_SND_HDA_POWER_SAVE
1262 static const struct hda_amp_list ad1986a_loopbacks[] = {
1263 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1264 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1265 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1266 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1267 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1272 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1274 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1275 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1278 static int patch_ad1986a(struct hda_codec *codec)
1280 struct ad198x_spec *spec;
1281 int err, board_config;
1283 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1289 err = snd_hda_attach_beep_device(codec, 0x19);
1294 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1296 spec->multiout.max_channels = 6;
1297 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1298 spec->multiout.dac_nids = ad1986a_dac_nids;
1299 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1300 spec->num_adc_nids = 1;
1301 spec->adc_nids = ad1986a_adc_nids;
1302 spec->capsrc_nids = ad1986a_capsrc_nids;
1303 spec->input_mux = &ad1986a_capture_source;
1304 spec->num_mixers = 1;
1305 spec->mixers[0] = ad1986a_mixers;
1306 spec->num_init_verbs = 1;
1307 spec->init_verbs[0] = ad1986a_init_verbs;
1308 #ifdef CONFIG_SND_HDA_POWER_SAVE
1309 spec->loopback.amplist = ad1986a_loopbacks;
1311 spec->vmaster_nid = 0x1b;
1312 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1314 codec->patch_ops = ad198x_patch_ops;
1316 /* override some parameters */
1317 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1320 switch (board_config) {
1321 case AD1986A_3STACK:
1322 spec->num_mixers = 2;
1323 spec->mixers[1] = ad1986a_3st_mixers;
1324 spec->num_init_verbs = 2;
1325 spec->init_verbs[1] = ad1986a_ch2_init;
1326 spec->channel_mode = ad1986a_modes;
1327 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1328 spec->need_dac_fix = 1;
1329 spec->multiout.max_channels = 2;
1330 spec->multiout.num_dacs = 1;
1332 case AD1986A_LAPTOP:
1333 spec->mixers[0] = ad1986a_laptop_mixers;
1334 spec->multiout.max_channels = 2;
1335 spec->multiout.num_dacs = 1;
1336 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1338 case AD1986A_LAPTOP_EAPD:
1339 spec->num_mixers = 3;
1340 spec->mixers[0] = ad1986a_laptop_master_mixers;
1341 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1342 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1343 spec->num_init_verbs = 2;
1344 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1345 spec->multiout.max_channels = 2;
1346 spec->multiout.num_dacs = 1;
1347 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1348 if (!is_jack_available(codec, 0x25))
1349 spec->multiout.dig_out_nid = 0;
1350 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1352 case AD1986A_SAMSUNG:
1353 spec->num_mixers = 2;
1354 spec->mixers[0] = ad1986a_laptop_master_mixers;
1355 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1356 spec->num_init_verbs = 3;
1357 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1358 spec->init_verbs[2] = ad1986a_automic_verbs;
1359 spec->multiout.max_channels = 2;
1360 spec->multiout.num_dacs = 1;
1361 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1362 if (!is_jack_available(codec, 0x25))
1363 spec->multiout.dig_out_nid = 0;
1364 spec->input_mux = &ad1986a_automic_capture_source;
1365 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1366 codec->patch_ops.init = ad1986a_automic_init;
1368 case AD1986A_SAMSUNG_P50:
1369 spec->num_mixers = 2;
1370 spec->mixers[0] = ad1986a_automute_master_mixers;
1371 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1372 spec->num_init_verbs = 4;
1373 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1374 spec->init_verbs[2] = ad1986a_automic_verbs;
1375 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1376 spec->multiout.max_channels = 2;
1377 spec->multiout.num_dacs = 1;
1378 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1379 if (!is_jack_available(codec, 0x25))
1380 spec->multiout.dig_out_nid = 0;
1381 spec->input_mux = &ad1986a_automic_capture_source;
1382 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1383 codec->patch_ops.init = ad1986a_samsung_p50_init;
1385 case AD1986A_LAPTOP_AUTOMUTE:
1386 spec->num_mixers = 3;
1387 spec->mixers[0] = ad1986a_automute_master_mixers;
1388 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1389 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1390 spec->num_init_verbs = 3;
1391 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1392 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1393 spec->multiout.max_channels = 2;
1394 spec->multiout.num_dacs = 1;
1395 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1396 if (!is_jack_available(codec, 0x25))
1397 spec->multiout.dig_out_nid = 0;
1398 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1399 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1400 codec->patch_ops.init = ad1986a_hp_init;
1401 /* Lenovo N100 seems to report the reversed bit
1402 * for HP jack-sensing
1404 spec->inv_jack_detect = 1;
1407 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1408 spec->num_init_verbs = 2;
1409 spec->init_verbs[1] = ad1986a_ultra_init;
1410 spec->multiout.max_channels = 2;
1411 spec->multiout.num_dacs = 1;
1412 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1413 spec->multiout.dig_out_nid = 0;
1417 /* AD1986A has a hardware problem that it can't share a stream
1418 * with multiple output pins. The copy of front to surrounds
1419 * causes noisy or silent outputs at a certain timing, e.g.
1420 * changing the volume.
1421 * So, let's disable the shared stream.
1423 spec->multiout.no_share_stream = 1;
1425 codec->no_trigger_sense = 1;
1426 codec->no_sticky_stream = 1;
1435 #define AD1983_SPDIF_OUT 0x02
1436 #define AD1983_DAC 0x03
1437 #define AD1983_ADC 0x04
1439 static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1440 static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1441 static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1443 static const struct hda_input_mux ad1983_capture_source = {
1449 { "Mix Mono", 0x3 },
1454 * SPDIF playback route
1456 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1458 static const char * const texts[] = { "PCM", "ADC" };
1460 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1462 uinfo->value.enumerated.items = 2;
1463 if (uinfo->value.enumerated.item > 1)
1464 uinfo->value.enumerated.item = 1;
1465 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1469 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1471 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1472 struct ad198x_spec *spec = codec->spec;
1474 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1478 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1480 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1481 struct ad198x_spec *spec = codec->spec;
1483 if (ucontrol->value.enumerated.item[0] > 1)
1485 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1486 spec->spdif_route = ucontrol->value.enumerated.item[0];
1487 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1488 AC_VERB_SET_CONNECT_SEL,
1495 static const struct snd_kcontrol_new ad1983_mixers[] = {
1496 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1497 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1498 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1499 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1500 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1507 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
1509 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1512 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1513 .name = "Capture Source",
1514 .info = ad198x_mux_enum_info,
1515 .get = ad198x_mux_enum_get,
1516 .put = ad198x_mux_enum_put,
1519 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1520 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1521 .info = ad1983_spdif_route_info,
1522 .get = ad1983_spdif_route_get,
1523 .put = ad1983_spdif_route_put,
1528 static const struct hda_verb ad1983_init_verbs[] = {
1529 /* Front, HP, Mono; mute as default */
1530 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1531 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1532 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1533 /* Beep, PCM, Mic, Line-In: mute */
1534 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1535 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1536 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1537 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1538 /* Front, HP selectors; from Mix */
1539 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1540 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1541 /* Mono selector; from Mix */
1542 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1543 /* Mic selector; Mic */
1544 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1545 /* Line-in selector: Line-in */
1546 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1547 /* Mic boost: 0dB */
1548 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1549 /* Record selector: mic */
1550 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1551 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1552 /* SPDIF route: PCM */
1553 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1555 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1557 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1559 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1561 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1563 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1567 #ifdef CONFIG_SND_HDA_POWER_SAVE
1568 static const struct hda_amp_list ad1983_loopbacks[] = {
1569 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1570 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1575 static int patch_ad1983(struct hda_codec *codec)
1577 struct ad198x_spec *spec;
1580 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1586 err = snd_hda_attach_beep_device(codec, 0x10);
1591 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1593 spec->multiout.max_channels = 2;
1594 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1595 spec->multiout.dac_nids = ad1983_dac_nids;
1596 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1597 spec->num_adc_nids = 1;
1598 spec->adc_nids = ad1983_adc_nids;
1599 spec->capsrc_nids = ad1983_capsrc_nids;
1600 spec->input_mux = &ad1983_capture_source;
1601 spec->num_mixers = 1;
1602 spec->mixers[0] = ad1983_mixers;
1603 spec->num_init_verbs = 1;
1604 spec->init_verbs[0] = ad1983_init_verbs;
1605 spec->spdif_route = 0;
1606 #ifdef CONFIG_SND_HDA_POWER_SAVE
1607 spec->loopback.amplist = ad1983_loopbacks;
1609 spec->vmaster_nid = 0x05;
1611 codec->patch_ops = ad198x_patch_ops;
1613 codec->no_trigger_sense = 1;
1614 codec->no_sticky_stream = 1;
1621 * AD1981 HD specific
1624 #define AD1981_SPDIF_OUT 0x02
1625 #define AD1981_DAC 0x03
1626 #define AD1981_ADC 0x04
1628 static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1629 static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1630 static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1632 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1633 static const struct hda_input_mux ad1981_capture_source = {
1636 { "Front Mic", 0x0 },
1639 { "Mix Mono", 0x3 },
1646 static const struct snd_kcontrol_new ad1981_mixers[] = {
1647 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1648 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1649 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1650 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1651 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1652 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1653 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1654 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1655 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1656 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1657 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1658 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1659 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1660 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1661 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1662 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1663 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1664 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1665 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1666 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1667 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1668 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671 .name = "Capture Source",
1672 .info = ad198x_mux_enum_info,
1673 .get = ad198x_mux_enum_get,
1674 .put = ad198x_mux_enum_put,
1676 /* identical with AD1983 */
1678 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1679 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1680 .info = ad1983_spdif_route_info,
1681 .get = ad1983_spdif_route_get,
1682 .put = ad1983_spdif_route_put,
1687 static const struct hda_verb ad1981_init_verbs[] = {
1688 /* Front, HP, Mono; mute as default */
1689 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1690 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1691 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1692 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1693 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1694 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1695 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1696 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1697 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1698 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1699 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1700 /* Front, HP selectors; from Mix */
1701 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1702 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1703 /* Mono selector; from Mix */
1704 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1705 /* Mic Mixer; select Front Mic */
1706 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1707 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1708 /* Mic boost: 0dB */
1709 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1710 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1711 /* Record selector: Front mic */
1712 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1713 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1714 /* SPDIF route: PCM */
1715 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1717 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1719 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1721 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1722 /* Front & Rear Mic Pins */
1723 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1724 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1726 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1728 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1729 /* Line-Out as Input: disabled */
1730 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1734 #ifdef CONFIG_SND_HDA_POWER_SAVE
1735 static const struct hda_amp_list ad1981_loopbacks[] = {
1736 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1737 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1738 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1739 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1740 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1746 * Patch for HP nx6320
1748 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1749 * speaker output enabled _and_ mute-LED off.
1752 #define AD1981_HP_EVENT 0x37
1753 #define AD1981_MIC_EVENT 0x38
1755 static const struct hda_verb ad1981_hp_init_verbs[] = {
1756 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1757 /* pin sensing on HP and Mic jacks */
1758 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1759 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1763 /* turn on/off EAPD (+ mute HP) as a master switch */
1764 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1765 struct snd_ctl_elem_value *ucontrol)
1767 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1768 struct ad198x_spec *spec = codec->spec;
1770 if (! ad198x_eapd_put(kcontrol, ucontrol))
1772 /* change speaker pin appropriately */
1773 snd_hda_codec_write(codec, 0x05, 0,
1774 AC_VERB_SET_PIN_WIDGET_CONTROL,
1775 spec->cur_eapd ? PIN_OUT : 0);
1776 /* toggle HP mute appropriately */
1777 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1779 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1783 /* bind volumes of both NID 0x05 and 0x06 */
1784 static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1785 .ops = &snd_hda_bind_vol,
1787 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1788 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1793 /* mute internal speaker if HP is plugged */
1794 static void ad1981_hp_automute(struct hda_codec *codec)
1796 unsigned int present;
1798 present = snd_hda_jack_detect(codec, 0x06);
1799 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1800 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1803 /* toggle input of built-in and mic jack appropriately */
1804 static void ad1981_hp_automic(struct hda_codec *codec)
1806 static const struct hda_verb mic_jack_on[] = {
1807 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1808 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1811 static const struct hda_verb mic_jack_off[] = {
1812 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1813 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1816 unsigned int present;
1818 present = snd_hda_jack_detect(codec, 0x08);
1820 snd_hda_sequence_write(codec, mic_jack_on);
1822 snd_hda_sequence_write(codec, mic_jack_off);
1825 /* unsolicited event for HP jack sensing */
1826 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1831 case AD1981_HP_EVENT:
1832 ad1981_hp_automute(codec);
1834 case AD1981_MIC_EVENT:
1835 ad1981_hp_automic(codec);
1840 static const struct hda_input_mux ad1981_hp_capture_source = {
1844 { "Docking-Station", 0x1 },
1849 static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
1850 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1852 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1853 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1854 .name = "Master Playback Switch",
1855 .info = ad198x_eapd_info,
1856 .get = ad198x_eapd_get,
1857 .put = ad1981_hp_master_sw_put,
1858 .private_value = 0x05,
1860 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1861 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1863 /* FIXME: analog mic/line loopback doesn't work with my tests...
1864 * (although recording is OK)
1866 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1867 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1868 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1869 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1870 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1871 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1872 /* FIXME: does this laptop have analog CD connection? */
1873 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1874 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1876 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1877 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1878 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1879 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1881 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1882 .name = "Capture Source",
1883 .info = ad198x_mux_enum_info,
1884 .get = ad198x_mux_enum_get,
1885 .put = ad198x_mux_enum_put,
1890 /* initialize jack-sensing, too */
1891 static int ad1981_hp_init(struct hda_codec *codec)
1894 ad1981_hp_automute(codec);
1895 ad1981_hp_automic(codec);
1899 /* configuration for Toshiba Laptops */
1900 static const struct hda_verb ad1981_toshiba_init_verbs[] = {
1901 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1902 /* pin sensing on HP and Mic jacks */
1903 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1904 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1908 static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1909 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1910 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1914 /* configuration for Lenovo Thinkpad T60 */
1915 static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1916 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1917 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1918 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1919 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1920 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1921 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1922 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1923 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1924 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1925 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1926 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1928 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1929 .name = "Capture Source",
1930 .info = ad198x_mux_enum_info,
1931 .get = ad198x_mux_enum_get,
1932 .put = ad198x_mux_enum_put,
1934 /* identical with AD1983 */
1936 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1937 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1938 .info = ad1983_spdif_route_info,
1939 .get = ad1983_spdif_route_get,
1940 .put = ad1983_spdif_route_put,
1945 static const struct hda_input_mux ad1981_thinkpad_capture_source = {
1963 static const char * const ad1981_models[AD1981_MODELS] = {
1965 [AD1981_THINKPAD] = "thinkpad",
1966 [AD1981_BASIC] = "basic",
1967 [AD1981_TOSHIBA] = "toshiba"
1970 static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
1971 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1972 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1974 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1975 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1976 /* Lenovo Thinkpad T60/X60/Z6xx */
1977 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1978 /* HP nx6320 (reversed SSID, H/W bug) */
1979 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1983 static int patch_ad1981(struct hda_codec *codec)
1985 struct ad198x_spec *spec;
1986 int err, board_config;
1988 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1994 err = snd_hda_attach_beep_device(codec, 0x10);
1999 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2001 spec->multiout.max_channels = 2;
2002 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
2003 spec->multiout.dac_nids = ad1981_dac_nids;
2004 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
2005 spec->num_adc_nids = 1;
2006 spec->adc_nids = ad1981_adc_nids;
2007 spec->capsrc_nids = ad1981_capsrc_nids;
2008 spec->input_mux = &ad1981_capture_source;
2009 spec->num_mixers = 1;
2010 spec->mixers[0] = ad1981_mixers;
2011 spec->num_init_verbs = 1;
2012 spec->init_verbs[0] = ad1981_init_verbs;
2013 spec->spdif_route = 0;
2014 #ifdef CONFIG_SND_HDA_POWER_SAVE
2015 spec->loopback.amplist = ad1981_loopbacks;
2017 spec->vmaster_nid = 0x05;
2019 codec->patch_ops = ad198x_patch_ops;
2021 /* override some parameters */
2022 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
2025 switch (board_config) {
2027 spec->mixers[0] = ad1981_hp_mixers;
2028 spec->num_init_verbs = 2;
2029 spec->init_verbs[1] = ad1981_hp_init_verbs;
2030 if (!is_jack_available(codec, 0x0a))
2031 spec->multiout.dig_out_nid = 0;
2032 spec->input_mux = &ad1981_hp_capture_source;
2034 codec->patch_ops.init = ad1981_hp_init;
2035 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2036 /* set the upper-limit for mixer amp to 0dB for avoiding the
2037 * possible damage by overloading
2039 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2040 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2041 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2042 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2043 (1 << AC_AMPCAP_MUTE_SHIFT));
2045 case AD1981_THINKPAD:
2046 spec->mixers[0] = ad1981_thinkpad_mixers;
2047 spec->input_mux = &ad1981_thinkpad_capture_source;
2048 /* set the upper-limit for mixer amp to 0dB for avoiding the
2049 * possible damage by overloading
2051 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2052 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2053 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2054 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2055 (1 << AC_AMPCAP_MUTE_SHIFT));
2057 case AD1981_TOSHIBA:
2058 spec->mixers[0] = ad1981_hp_mixers;
2059 spec->mixers[1] = ad1981_toshiba_mixers;
2060 spec->num_init_verbs = 2;
2061 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
2062 spec->multiout.dig_out_nid = 0;
2063 spec->input_mux = &ad1981_hp_capture_source;
2064 codec->patch_ops.init = ad1981_hp_init;
2065 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2069 codec->no_trigger_sense = 1;
2070 codec->no_sticky_stream = 1;
2079 * Output pins and routes
2081 * Pin Mix Sel DAC (*)
2082 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
2083 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
2084 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
2085 * port-D 0x12 (mute/hp) <- 0x29 <- 04
2086 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
2087 * port-F 0x16 (mute) <- 0x2a <- 06
2088 * port-G 0x24 (mute) <- 0x27 <- 05
2089 * port-H 0x25 (mute) <- 0x28 <- 0a
2090 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
2092 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
2093 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
2095 * Input pins and routes
2097 * pin boost mix input # / adc input #
2098 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
2099 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
2100 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
2101 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
2102 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
2103 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
2104 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
2105 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2109 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2110 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2112 * Inputs of Analog Mix (0x20)
2113 * 0:Port-B (front mic)
2114 * 1:Port-C/G/H (line-in)
2116 * 3:Port-D (line-in/2)
2117 * 4:Port-E/G/H (mic-in)
2118 * 5:Port-F (mic2-in)
2124 * 1:Port-B (front mic-in)
2125 * 2:Port-C (line-in)
2126 * 3:Port-F (mic2-in)
2131 * 8:Port-D (line-in/2)
2134 * Proposed pin assignments by the datasheet
2137 * Port-A front headphone
2147 * Port-A front headphone
2149 * C rear line-in/surround
2151 * E rear mic-in/CLFE
2157 * D internal speaker (with EAPD)
2158 * E/F quad mic array
2174 /* reivision id to check workarounds */
2175 #define AD1988A_REV2 0x100200
2177 #define is_rev2(codec) \
2178 ((codec)->vendor_id == 0x11d41988 && \
2179 (codec)->revision_id == AD1988A_REV2)
2185 static const hda_nid_t ad1988_6stack_dac_nids[4] = {
2186 0x04, 0x06, 0x05, 0x0a
2189 static const hda_nid_t ad1988_3stack_dac_nids[3] = {
2193 /* for AD1988A revision-2, DAC2-4 are swapped */
2194 static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2195 0x04, 0x05, 0x0a, 0x06
2198 static const hda_nid_t ad1988_alt_dac_nid[1] = {
2202 static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2206 static const hda_nid_t ad1988_adc_nids[3] = {
2210 static const hda_nid_t ad1988_capsrc_nids[3] = {
2214 #define AD1988_SPDIF_OUT 0x02
2215 #define AD1988_SPDIF_OUT_HDMI 0x0b
2216 #define AD1988_SPDIF_IN 0x07
2218 static const hda_nid_t ad1989b_slave_dig_outs[] = {
2219 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2222 static const struct hda_input_mux ad1988_6stack_capture_source = {
2225 { "Front Mic", 0x1 }, /* port-B */
2226 { "Line", 0x2 }, /* port-C */
2227 { "Mic", 0x4 }, /* port-E */
2233 static const struct hda_input_mux ad1988_laptop_capture_source = {
2236 { "Mic/Line", 0x1 }, /* port-B */
2244 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2245 struct snd_ctl_elem_info *uinfo)
2247 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2248 struct ad198x_spec *spec = codec->spec;
2249 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2250 spec->num_channel_mode);
2253 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2254 struct snd_ctl_elem_value *ucontrol)
2256 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2257 struct ad198x_spec *spec = codec->spec;
2258 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2259 spec->num_channel_mode, spec->multiout.max_channels);
2262 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2263 struct snd_ctl_elem_value *ucontrol)
2265 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2266 struct ad198x_spec *spec = codec->spec;
2267 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2268 spec->num_channel_mode,
2269 &spec->multiout.max_channels);
2270 if (err >= 0 && spec->need_dac_fix)
2271 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2275 static const struct snd_kcontrol_new ad1988_hp_mixers[] = {
2277 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2278 .name = "Independent HP",
2279 .info = ad1988_independent_hp_info,
2280 .get = ad1988_independent_hp_get,
2281 .put = ad1988_independent_hp_put,
2287 static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2288 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2289 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2290 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2291 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2292 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2296 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2297 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2298 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2299 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2300 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2301 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2305 static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2306 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2307 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2308 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2309 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2310 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2311 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2312 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2313 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2315 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2316 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2317 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2318 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2319 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2320 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2321 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2322 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2324 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2325 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2327 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2328 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2333 static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2334 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2335 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2336 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2337 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2341 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2342 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2343 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2344 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2345 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2349 static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2350 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2351 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2352 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2353 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2354 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2355 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2356 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2358 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2359 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2360 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2361 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2362 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2363 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2364 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2365 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2367 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2368 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2370 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2371 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2374 .name = "Channel Mode",
2375 .info = ad198x_ch_mode_info,
2376 .get = ad198x_ch_mode_get,
2377 .put = ad198x_ch_mode_put,
2384 static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2385 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2386 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2387 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2388 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2390 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2391 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2392 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2393 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2394 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2395 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2397 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2398 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2400 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2403 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2404 .name = "External Amplifier",
2405 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2406 .info = ad198x_eapd_info,
2407 .get = ad198x_eapd_get,
2408 .put = ad198x_eapd_put,
2409 .private_value = 0x12, /* port-D */
2416 static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
2417 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2418 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2419 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2420 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2421 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2422 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2425 /* The multiple "Capture Source" controls confuse alsamixer
2426 * So call somewhat different..
2428 /* .name = "Capture Source", */
2429 .name = "Input Source",
2431 .info = ad198x_mux_enum_info,
2432 .get = ad198x_mux_enum_get,
2433 .put = ad198x_mux_enum_put,
2438 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2439 struct snd_ctl_elem_info *uinfo)
2441 static const char * const texts[] = {
2442 "PCM", "ADC1", "ADC2", "ADC3"
2444 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2446 uinfo->value.enumerated.items = 4;
2447 if (uinfo->value.enumerated.item >= 4)
2448 uinfo->value.enumerated.item = 3;
2449 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2453 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2454 struct snd_ctl_elem_value *ucontrol)
2456 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2459 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2462 ucontrol->value.enumerated.item[0] = 0;
2464 sel = snd_hda_codec_read(codec, 0x0b, 0,
2465 AC_VERB_GET_CONNECT_SEL, 0);
2470 ucontrol->value.enumerated.item[0] = sel;
2475 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2476 struct snd_ctl_elem_value *ucontrol)
2478 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2479 unsigned int val, sel;
2482 val = ucontrol->value.enumerated.item[0];
2486 sel = snd_hda_codec_read(codec, 0x1d, 0,
2487 AC_VERB_GET_AMP_GAIN_MUTE,
2489 change = sel & 0x80;
2491 snd_hda_codec_write_cache(codec, 0x1d, 0,
2492 AC_VERB_SET_AMP_GAIN_MUTE,
2494 snd_hda_codec_write_cache(codec, 0x1d, 0,
2495 AC_VERB_SET_AMP_GAIN_MUTE,
2499 sel = snd_hda_codec_read(codec, 0x1d, 0,
2500 AC_VERB_GET_AMP_GAIN_MUTE,
2501 AC_AMP_GET_INPUT | 0x01);
2502 change = sel & 0x80;
2504 snd_hda_codec_write_cache(codec, 0x1d, 0,
2505 AC_VERB_SET_AMP_GAIN_MUTE,
2507 snd_hda_codec_write_cache(codec, 0x1d, 0,
2508 AC_VERB_SET_AMP_GAIN_MUTE,
2511 sel = snd_hda_codec_read(codec, 0x0b, 0,
2512 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2513 change |= sel != val;
2515 snd_hda_codec_write_cache(codec, 0x0b, 0,
2516 AC_VERB_SET_CONNECT_SEL,
2522 static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2523 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2525 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2526 .name = "IEC958 Playback Source",
2527 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2528 .info = ad1988_spdif_playback_source_info,
2529 .get = ad1988_spdif_playback_source_get,
2530 .put = ad1988_spdif_playback_source_put,
2535 static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2536 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2540 static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2541 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2542 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2547 * initialization verbs
2551 * for 6-stack (+dig)
2553 static const struct hda_verb ad1988_6stack_init_verbs[] = {
2554 /* Front, Surround, CLFE, side DAC; unmute as default */
2555 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2556 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2557 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2558 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2559 /* Port-A front headphon path */
2560 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2561 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2562 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2563 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2564 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2565 /* Port-D line-out path */
2566 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2567 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2568 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2569 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2570 /* Port-F surround path */
2571 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2572 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2573 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2574 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2575 /* Port-G CLFE path */
2576 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2577 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2578 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2579 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2580 /* Port-H side path */
2581 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2582 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2583 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2584 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2586 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2587 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2588 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2589 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2590 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2591 /* Port-B front mic-in path */
2592 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2593 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2594 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2595 /* Port-C line-in path */
2596 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2597 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2598 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2599 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2600 /* Port-E mic-in path */
2601 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2602 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2603 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2604 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2605 /* Analog CD Input */
2606 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2607 /* Analog Mix output amp */
2608 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2613 static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
2614 /* Headphone; unmute as default */
2615 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2616 /* Port-A front headphon path */
2617 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2618 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2619 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2620 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2621 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2626 static const struct hda_verb ad1988_capture_init_verbs[] = {
2627 /* mute analog mix */
2628 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2635 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2636 /* select ADCs - front-mic */
2637 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2638 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2639 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2644 static const struct hda_verb ad1988_spdif_init_verbs[] = {
2646 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2647 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2648 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2649 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2651 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2656 static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
2657 /* unmute SPDIF input pin */
2658 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2662 /* AD1989 has no ADC -> SPDIF route */
2663 static const struct hda_verb ad1989_spdif_init_verbs[] = {
2664 /* SPDIF-1 out pin */
2665 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2666 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2667 /* SPDIF-2/HDMI out pin */
2668 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2669 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2674 * verbs for 3stack (+dig)
2676 static const struct hda_verb ad1988_3stack_ch2_init[] = {
2677 /* set port-C to line-in */
2678 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2679 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2680 /* set port-E to mic-in */
2681 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2682 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2686 static const struct hda_verb ad1988_3stack_ch6_init[] = {
2687 /* set port-C to surround out */
2688 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2689 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2690 /* set port-E to CLFE out */
2691 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2692 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2696 static const struct hda_channel_mode ad1988_3stack_modes[2] = {
2697 { 2, ad1988_3stack_ch2_init },
2698 { 6, ad1988_3stack_ch6_init },
2701 static const struct hda_verb ad1988_3stack_init_verbs[] = {
2702 /* Front, Surround, CLFE, side DAC; unmute as default */
2703 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2704 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2705 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2706 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2707 /* Port-A front headphon path */
2708 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2709 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2710 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2711 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2712 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2713 /* Port-D line-out path */
2714 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2715 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2716 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2717 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2719 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2720 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2721 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2722 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2723 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2724 /* Port-B front mic-in path */
2725 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2726 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2727 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2728 /* Port-C line-in/surround path - 6ch mode as default */
2729 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2730 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2731 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2732 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2733 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2734 /* Port-E mic-in/CLFE path - 6ch mode as default */
2735 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2736 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2737 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2738 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2739 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2740 /* mute analog mix */
2741 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2742 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2743 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2744 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2745 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2746 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2747 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2748 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2749 /* select ADCs - front-mic */
2750 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2751 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2752 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2753 /* Analog Mix output amp */
2754 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2759 * verbs for laptop mode (+dig)
2761 static const struct hda_verb ad1988_laptop_hp_on[] = {
2762 /* unmute port-A and mute port-D */
2763 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2764 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2767 static const struct hda_verb ad1988_laptop_hp_off[] = {
2768 /* mute port-A and unmute port-D */
2769 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2770 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2774 #define AD1988_HP_EVENT 0x01
2776 static const struct hda_verb ad1988_laptop_init_verbs[] = {
2777 /* Front, Surround, CLFE, side DAC; unmute as default */
2778 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2779 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2780 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2781 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2782 /* Port-A front headphon path */
2783 {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2784 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2786 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2787 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2788 /* unsolicited event for pin-sense */
2789 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2790 /* Port-D line-out path + EAPD */
2791 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2792 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2793 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2794 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2795 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2797 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2798 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2799 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2800 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2801 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2802 /* Port-B mic-in path */
2803 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2804 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2805 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2806 /* Port-C docking station - try to output */
2807 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2808 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2809 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2810 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2811 /* mute analog mix */
2812 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2813 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2814 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2815 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2816 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2817 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2818 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2819 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2820 /* select ADCs - mic */
2821 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2822 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2823 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2824 /* Analog Mix output amp */
2825 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2829 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2831 if ((res >> 26) != AD1988_HP_EVENT)
2833 if (snd_hda_jack_detect(codec, 0x11))
2834 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2836 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2839 #ifdef CONFIG_SND_HDA_POWER_SAVE
2840 static const struct hda_amp_list ad1988_loopbacks[] = {
2841 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2842 { 0x20, HDA_INPUT, 1 }, /* Line */
2843 { 0x20, HDA_INPUT, 4 }, /* Mic */
2844 { 0x20, HDA_INPUT, 6 }, /* CD */
2850 * Automatic parse of I/O pins from the BIOS configuration
2858 static const struct snd_kcontrol_new ad1988_control_templates[] = {
2859 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2860 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2861 HDA_BIND_MUTE(NULL, 0, 0, 0),
2864 /* add dynamic controls */
2865 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2868 struct snd_kcontrol_new *knew;
2870 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2871 knew = snd_array_new(&spec->kctls);
2874 *knew = ad1988_control_templates[type];
2875 knew->name = kstrdup(name, GFP_KERNEL);
2878 if (get_amp_nid_(val))
2879 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2880 knew->private_value = val;
2884 #define AD1988_PIN_CD_NID 0x18
2885 #define AD1988_PIN_BEEP_NID 0x10
2887 static const hda_nid_t ad1988_mixer_nids[8] = {
2888 /* A B C D E F G H */
2889 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2892 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2894 static const hda_nid_t idx_to_dac[8] = {
2895 /* A B C D E F G H */
2896 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2898 static const hda_nid_t idx_to_dac_rev2[8] = {
2899 /* A B C D E F G H */
2900 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2903 return idx_to_dac_rev2[idx];
2905 return idx_to_dac[idx];
2908 static const hda_nid_t ad1988_boost_nids[8] = {
2909 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2912 static int ad1988_pin_idx(hda_nid_t nid)
2914 static const hda_nid_t ad1988_io_pins[8] = {
2915 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2918 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2919 if (ad1988_io_pins[i] == nid)
2921 return 0; /* should be -1 */
2924 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2926 static const int loopback_idx[8] = {
2927 2, 0, 1, 3, 4, 5, 1, 4
2930 case AD1988_PIN_CD_NID:
2933 return loopback_idx[ad1988_pin_idx(nid)];
2937 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2939 static const int adc_idx[8] = {
2940 0, 1, 2, 8, 4, 3, 6, 7
2943 case AD1988_PIN_CD_NID:
2946 return adc_idx[ad1988_pin_idx(nid)];
2950 /* fill in the dac_nids table from the parsed pin configuration */
2951 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2952 const struct auto_pin_cfg *cfg)
2954 struct ad198x_spec *spec = codec->spec;
2957 spec->multiout.dac_nids = spec->private_dac_nids;
2959 /* check the pins hardwired to audio widget */
2960 for (i = 0; i < cfg->line_outs; i++) {
2961 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2962 spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2964 spec->multiout.num_dacs = cfg->line_outs;
2968 /* add playback controls from the parsed DAC table */
2969 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2970 const struct auto_pin_cfg *cfg)
2973 static const char * const chname[4] = {
2974 "Front", "Surround", NULL /*CLFE*/, "Side"
2979 for (i = 0; i < cfg->line_outs; i++) {
2980 hda_nid_t dac = spec->multiout.dac_nids[i];
2983 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2986 err = add_control(spec, AD_CTL_WIDGET_VOL,
2987 "Center Playback Volume",
2988 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2991 err = add_control(spec, AD_CTL_WIDGET_VOL,
2992 "LFE Playback Volume",
2993 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2996 err = add_control(spec, AD_CTL_BIND_MUTE,
2997 "Center Playback Switch",
2998 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
3001 err = add_control(spec, AD_CTL_BIND_MUTE,
3002 "LFE Playback Switch",
3003 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
3007 sprintf(name, "%s Playback Volume", chname[i]);
3008 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
3009 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
3012 sprintf(name, "%s Playback Switch", chname[i]);
3013 err = add_control(spec, AD_CTL_BIND_MUTE, name,
3014 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
3022 /* add playback controls for speaker and HP outputs */
3023 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
3026 struct ad198x_spec *spec = codec->spec;
3034 idx = ad1988_pin_idx(pin);
3035 nid = ad1988_idx_to_dac(codec, idx);
3036 /* check whether the corresponding DAC was already taken */
3037 for (i = 0; i < spec->autocfg.line_outs; i++) {
3038 hda_nid_t pin = spec->autocfg.line_out_pins[i];
3039 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
3043 if (i >= spec->autocfg.line_outs) {
3044 /* specify the DAC as the extra output */
3045 if (!spec->multiout.hp_nid)
3046 spec->multiout.hp_nid = nid;
3048 spec->multiout.extra_out_nid[0] = nid;
3049 /* control HP volume/switch on the output mixer amp */
3050 sprintf(name, "%s Playback Volume", pfx);
3051 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
3052 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
3056 nid = ad1988_mixer_nids[idx];
3057 sprintf(name, "%s Playback Switch", pfx);
3058 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
3059 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
3064 /* create input playback/capture controls for the given pin */
3065 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
3066 const char *ctlname, int ctlidx, int boost)
3071 sprintf(name, "%s Playback Volume", ctlname);
3072 idx = ad1988_pin_to_loopback_idx(pin);
3073 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
3074 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
3076 sprintf(name, "%s Playback Switch", ctlname);
3077 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
3078 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
3082 idx = ad1988_pin_idx(pin);
3083 bnid = ad1988_boost_nids[idx];
3085 sprintf(name, "%s Boost Volume", ctlname);
3086 return add_control(spec, AD_CTL_WIDGET_VOL, name,
3087 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
3094 /* create playback/capture controls for input pins */
3095 static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
3096 const struct auto_pin_cfg *cfg)
3098 struct ad198x_spec *spec = codec->spec;
3099 struct hda_input_mux *imux = &spec->private_imux;
3100 int i, err, type, type_idx;
3102 for (i = 0; i < cfg->num_inputs; i++) {
3104 type = cfg->inputs[i].type;
3105 label = hda_get_autocfg_input_label(codec, cfg, i);
3106 snd_hda_add_imux_item(imux, label,
3107 ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
3109 err = new_analog_input(spec, cfg->inputs[i].pin,
3111 type == AUTO_PIN_MIC);
3115 snd_hda_add_imux_item(imux, "Mix", 9, NULL);
3117 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
3118 "Analog Mix Playback Volume",
3119 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3121 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
3122 "Analog Mix Playback Switch",
3123 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3129 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
3130 hda_nid_t nid, int pin_type,
3134 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3135 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3137 case 0x11: /* port-A - DAC 03 */
3138 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3140 case 0x14: /* port-B - DAC 06 */
3141 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
3143 case 0x15: /* port-C - DAC 05 */
3144 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3146 case 0x17: /* port-E - DAC 0a */
3147 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3149 case 0x13: /* mono - DAC 04 */
3150 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3155 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
3157 struct ad198x_spec *spec = codec->spec;
3160 for (i = 0; i < spec->autocfg.line_outs; i++) {
3161 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3162 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3166 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
3168 struct ad198x_spec *spec = codec->spec;
3171 pin = spec->autocfg.speaker_pins[0];
3172 if (pin) /* connect to front */
3173 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3174 pin = spec->autocfg.hp_pins[0];
3175 if (pin) /* connect to front */
3176 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3179 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3181 struct ad198x_spec *spec = codec->spec;
3182 const struct auto_pin_cfg *cfg = &spec->autocfg;
3185 for (i = 0; i < cfg->num_inputs; i++) {
3186 hda_nid_t nid = cfg->inputs[i].pin;
3187 int type = cfg->inputs[i].type;
3189 case 0x15: /* port-C */
3190 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3192 case 0x17: /* port-E */
3193 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3196 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3197 type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
3198 if (nid != AD1988_PIN_CD_NID)
3199 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3201 idx = ad1988_pin_idx(nid);
3202 if (ad1988_boost_nids[idx])
3203 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3204 AC_VERB_SET_AMP_GAIN_MUTE,
3209 /* parse the BIOS configuration and set up the alc_spec */
3210 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3211 static int ad1988_parse_auto_config(struct hda_codec *codec)
3213 struct ad198x_spec *spec = codec->spec;
3216 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3218 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3220 if (! spec->autocfg.line_outs)
3221 return 0; /* can't find valid BIOS pin config */
3222 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3223 (err = ad1988_auto_create_extra_out(codec,
3224 spec->autocfg.speaker_pins[0],
3226 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3227 "Headphone")) < 0 ||
3228 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3231 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3233 if (spec->autocfg.dig_outs)
3234 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3235 if (spec->autocfg.dig_in_pin)
3236 spec->dig_in_nid = AD1988_SPDIF_IN;
3238 if (spec->kctls.list)
3239 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3241 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3243 spec->input_mux = &spec->private_imux;
3248 /* init callback for auto-configuration model -- overriding the default init */
3249 static int ad1988_auto_init(struct hda_codec *codec)
3252 ad1988_auto_init_multi_out(codec);
3253 ad1988_auto_init_extra_out(codec);
3254 ad1988_auto_init_analog_input(codec);
3261 static const char * const ad1988_models[AD1988_MODEL_LAST] = {
3262 [AD1988_6STACK] = "6stack",
3263 [AD1988_6STACK_DIG] = "6stack-dig",
3264 [AD1988_3STACK] = "3stack",
3265 [AD1988_3STACK_DIG] = "3stack-dig",
3266 [AD1988_LAPTOP] = "laptop",
3267 [AD1988_LAPTOP_DIG] = "laptop-dig",
3268 [AD1988_AUTO] = "auto",
3271 static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
3272 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3273 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3274 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3275 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
3276 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3280 static int patch_ad1988(struct hda_codec *codec)
3282 struct ad198x_spec *spec;
3283 int err, board_config;
3285 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3292 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3294 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3295 ad1988_models, ad1988_cfg_tbl);
3296 if (board_config < 0) {
3297 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3299 board_config = AD1988_AUTO;
3302 if (board_config == AD1988_AUTO) {
3303 /* automatic parse from the BIOS config */
3304 err = ad1988_parse_auto_config(codec);
3309 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3310 board_config = AD1988_6STACK;
3314 err = snd_hda_attach_beep_device(codec, 0x10);
3319 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3321 if (!spec->multiout.hp_nid)
3322 spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
3323 switch (board_config) {
3325 case AD1988_6STACK_DIG:
3326 spec->multiout.max_channels = 8;
3327 spec->multiout.num_dacs = 4;
3329 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3331 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3332 spec->input_mux = &ad1988_6stack_capture_source;
3333 spec->num_mixers = 2;
3335 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3337 spec->mixers[0] = ad1988_6stack_mixers1;
3338 spec->mixers[1] = ad1988_6stack_mixers2;
3339 spec->num_init_verbs = 1;
3340 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3341 if (board_config == AD1988_6STACK_DIG) {
3342 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3343 spec->dig_in_nid = AD1988_SPDIF_IN;
3347 case AD1988_3STACK_DIG:
3348 spec->multiout.max_channels = 6;
3349 spec->multiout.num_dacs = 3;
3351 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3353 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3354 spec->input_mux = &ad1988_6stack_capture_source;
3355 spec->channel_mode = ad1988_3stack_modes;
3356 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3357 spec->num_mixers = 2;
3359 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3361 spec->mixers[0] = ad1988_3stack_mixers1;
3362 spec->mixers[1] = ad1988_3stack_mixers2;
3363 spec->num_init_verbs = 1;
3364 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3365 if (board_config == AD1988_3STACK_DIG)
3366 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3369 case AD1988_LAPTOP_DIG:
3370 spec->multiout.max_channels = 2;
3371 spec->multiout.num_dacs = 1;
3372 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3373 spec->input_mux = &ad1988_laptop_capture_source;
3374 spec->num_mixers = 1;
3375 spec->mixers[0] = ad1988_laptop_mixers;
3376 spec->inv_eapd = 1; /* inverted EAPD */
3377 spec->num_init_verbs = 1;
3378 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3379 if (board_config == AD1988_LAPTOP_DIG)
3380 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3384 if (spec->autocfg.hp_pins[0]) {
3385 spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
3386 spec->slave_vols = ad1988_6stack_fp_slave_vols;
3387 spec->slave_sws = ad1988_6stack_fp_slave_sws;
3388 spec->alt_dac_nid = ad1988_alt_dac_nid;
3389 spec->stream_analog_alt_playback =
3390 &ad198x_pcm_analog_alt_playback;
3393 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3394 spec->adc_nids = ad1988_adc_nids;
3395 spec->capsrc_nids = ad1988_capsrc_nids;
3396 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3397 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3398 if (spec->multiout.dig_out_nid) {
3399 if (codec->vendor_id >= 0x11d4989a) {
3400 spec->mixers[spec->num_mixers++] =
3401 ad1989_spdif_out_mixers;
3402 spec->init_verbs[spec->num_init_verbs++] =
3403 ad1989_spdif_init_verbs;
3404 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3406 spec->mixers[spec->num_mixers++] =
3407 ad1988_spdif_out_mixers;
3408 spec->init_verbs[spec->num_init_verbs++] =
3409 ad1988_spdif_init_verbs;
3412 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3413 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3414 spec->init_verbs[spec->num_init_verbs++] =
3415 ad1988_spdif_in_init_verbs;
3418 codec->patch_ops = ad198x_patch_ops;
3419 switch (board_config) {
3421 codec->patch_ops.init = ad1988_auto_init;
3424 case AD1988_LAPTOP_DIG:
3425 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3428 #ifdef CONFIG_SND_HDA_POWER_SAVE
3429 spec->loopback.amplist = ad1988_loopbacks;
3431 spec->vmaster_nid = 0x04;
3433 codec->no_trigger_sense = 1;
3434 codec->no_sticky_stream = 1;
3443 * port-B - front line/mic-in
3444 * port-E - aux in/out
3445 * port-F - aux in/out
3446 * port-C - rear line/mic-in
3447 * port-D - rear line/hp-out
3448 * port-A - front line/hp-out
3450 * AD1984 = AD1884 + two digital mic-ins
3453 * For simplicity, we share the single DAC for both HP and line-outs
3454 * right now. The inidividual playbacks could be easily implemented,
3455 * but no build-up framework is given, so far.
3458 static const hda_nid_t ad1884_dac_nids[1] = {
3462 static const hda_nid_t ad1884_adc_nids[2] = {
3466 static const hda_nid_t ad1884_capsrc_nids[2] = {
3470 #define AD1884_SPDIF_OUT 0x02
3472 static const struct hda_input_mux ad1884_capture_source = {
3475 { "Front Mic", 0x0 },
3482 static const struct snd_kcontrol_new ad1884_base_mixers[] = {
3483 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3484 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3485 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3486 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3487 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3488 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3489 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3490 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3491 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3492 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3493 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3494 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3495 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3496 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3497 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3498 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3499 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3500 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3503 /* The multiple "Capture Source" controls confuse alsamixer
3504 * So call somewhat different..
3506 /* .name = "Capture Source", */
3507 .name = "Input Source",
3509 .info = ad198x_mux_enum_info,
3510 .get = ad198x_mux_enum_get,
3511 .put = ad198x_mux_enum_put,
3513 /* SPDIF controls */
3514 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3517 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3518 /* identical with ad1983 */
3519 .info = ad1983_spdif_route_info,
3520 .get = ad1983_spdif_route_get,
3521 .put = ad1983_spdif_route_put,
3526 static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3527 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3528 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3529 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3531 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3537 * initialization verbs
3539 static const struct hda_verb ad1884_init_verbs[] = {
3540 /* DACs; mute as default */
3541 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3542 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3543 /* Port-A (HP) mixer */
3544 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3545 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3547 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3548 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3549 /* HP selector - select DAC2 */
3550 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3551 /* Port-D (Line-out) mixer */
3552 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3553 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3555 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3556 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3557 /* Mono-out mixer */
3558 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3559 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3561 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3562 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3564 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3565 /* Port-B (front mic) pin */
3566 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3567 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3568 /* Port-C (rear mic) pin */
3569 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3570 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3571 /* Analog mixer; mute as default */
3572 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3573 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3574 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3575 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3576 /* Analog Mix output amp */
3577 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3578 /* SPDIF output selector */
3579 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3580 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3584 #ifdef CONFIG_SND_HDA_POWER_SAVE
3585 static const struct hda_amp_list ad1884_loopbacks[] = {
3586 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3587 { 0x20, HDA_INPUT, 1 }, /* Mic */
3588 { 0x20, HDA_INPUT, 2 }, /* CD */
3589 { 0x20, HDA_INPUT, 4 }, /* Docking */
3594 static const char * const ad1884_slave_vols[] = {
3595 "PCM Playback Volume",
3596 "Mic Playback Volume",
3597 "Mono Playback Volume",
3598 "Front Mic Playback Volume",
3599 "Mic Playback Volume",
3600 "CD Playback Volume",
3601 "Internal Mic Playback Volume",
3602 "Docking Mic Playback Volume",
3603 /* "Beep Playback Volume", */
3604 "IEC958 Playback Volume",
3608 static int patch_ad1884(struct hda_codec *codec)
3610 struct ad198x_spec *spec;
3613 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3619 err = snd_hda_attach_beep_device(codec, 0x10);
3624 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3626 spec->multiout.max_channels = 2;
3627 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3628 spec->multiout.dac_nids = ad1884_dac_nids;
3629 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3630 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3631 spec->adc_nids = ad1884_adc_nids;
3632 spec->capsrc_nids = ad1884_capsrc_nids;
3633 spec->input_mux = &ad1884_capture_source;
3634 spec->num_mixers = 1;
3635 spec->mixers[0] = ad1884_base_mixers;
3636 spec->num_init_verbs = 1;
3637 spec->init_verbs[0] = ad1884_init_verbs;
3638 spec->spdif_route = 0;
3639 #ifdef CONFIG_SND_HDA_POWER_SAVE
3640 spec->loopback.amplist = ad1884_loopbacks;
3642 spec->vmaster_nid = 0x04;
3643 /* we need to cover all playback volumes */
3644 spec->slave_vols = ad1884_slave_vols;
3646 codec->patch_ops = ad198x_patch_ops;
3648 codec->no_trigger_sense = 1;
3649 codec->no_sticky_stream = 1;
3655 * Lenovo Thinkpad T61/X61
3657 static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3661 { "Internal Mic", 0x1 },
3663 { "Docking-Station", 0x4 },
3669 * Dell Precision T3400
3671 static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3674 { "Front Mic", 0x0 },
3681 static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3682 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3683 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3684 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3685 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3686 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3687 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3688 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3689 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3690 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3691 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3692 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3693 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3694 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3695 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3696 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3697 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3698 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3699 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3700 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3702 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3703 /* The multiple "Capture Source" controls confuse alsamixer
3704 * So call somewhat different..
3706 /* .name = "Capture Source", */
3707 .name = "Input Source",
3709 .info = ad198x_mux_enum_info,
3710 .get = ad198x_mux_enum_get,
3711 .put = ad198x_mux_enum_put,
3713 /* SPDIF controls */
3714 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3716 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3717 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3718 /* identical with ad1983 */
3719 .info = ad1983_spdif_route_info,
3720 .get = ad1983_spdif_route_get,
3721 .put = ad1983_spdif_route_put,
3726 /* additional verbs */
3727 static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3728 /* Port-E (docking station mic) pin */
3729 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3730 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3731 /* docking mic boost */
3732 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3733 /* Analog PC Beeper - allow firmware/ACPI beeps */
3734 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3735 /* Analog mixer - docking mic; mute as default */
3736 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3737 /* enable EAPD bit */
3738 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3743 * Dell Precision T3400
3745 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3746 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3747 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3748 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3749 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3750 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3751 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3752 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3753 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3754 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3755 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3756 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3757 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3758 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3759 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3760 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3762 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3763 /* The multiple "Capture Source" controls confuse alsamixer
3764 * So call somewhat different..
3766 /* .name = "Capture Source", */
3767 .name = "Input Source",
3769 .info = ad198x_mux_enum_info,
3770 .get = ad198x_mux_enum_get,
3771 .put = ad198x_mux_enum_put,
3776 /* Digial MIC ADC NID 0x05 + 0x06 */
3777 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3778 struct hda_codec *codec,
3779 unsigned int stream_tag,
3780 unsigned int format,
3781 struct snd_pcm_substream *substream)
3783 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3784 stream_tag, 0, format);
3788 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3789 struct hda_codec *codec,
3790 struct snd_pcm_substream *substream)
3792 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3796 static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3802 .prepare = ad1984_pcm_dmic_prepare,
3803 .cleanup = ad1984_pcm_dmic_cleanup
3807 static int ad1984_build_pcms(struct hda_codec *codec)
3809 struct ad198x_spec *spec = codec->spec;
3810 struct hda_pcm *info;
3813 err = ad198x_build_pcms(codec);
3817 info = spec->pcm_rec + codec->num_pcms;
3819 info->name = "AD1984 Digital Mic";
3820 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3828 AD1984_DELL_DESKTOP,
3832 static const char * const ad1984_models[AD1984_MODELS] = {
3833 [AD1984_BASIC] = "basic",
3834 [AD1984_THINKPAD] = "thinkpad",
3835 [AD1984_DELL_DESKTOP] = "dell_desktop",
3838 static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3839 /* Lenovo Thinkpad T61/X61 */
3840 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3841 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3842 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3846 static int patch_ad1984(struct hda_codec *codec)
3848 struct ad198x_spec *spec;
3849 int board_config, err;
3851 err = patch_ad1884(codec);
3855 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3856 ad1984_models, ad1984_cfg_tbl);
3857 switch (board_config) {
3859 /* additional digital mics */
3860 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3861 codec->patch_ops.build_pcms = ad1984_build_pcms;
3863 case AD1984_THINKPAD:
3864 if (codec->subsystem_id == 0x17aa20fb) {
3865 /* Thinpad X300 does not have the ability to do SPDIF,
3866 or attach to docking station to use SPDIF */
3867 spec->multiout.dig_out_nid = 0;
3869 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3870 spec->input_mux = &ad1984_thinkpad_capture_source;
3871 spec->mixers[0] = ad1984_thinkpad_mixers;
3872 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3873 spec->analog_beep = 1;
3875 case AD1984_DELL_DESKTOP:
3876 spec->multiout.dig_out_nid = 0;
3877 spec->input_mux = &ad1984_dell_desktop_capture_source;
3878 spec->mixers[0] = ad1984_dell_desktop_mixers;
3886 * AD1883 / AD1884A / AD1984A / AD1984B
3888 * port-B (0x14) - front mic-in
3889 * port-E (0x1c) - rear mic-in
3890 * port-F (0x16) - CD / ext out
3891 * port-C (0x15) - rear line-in
3892 * port-D (0x12) - rear line-out
3893 * port-A (0x11) - front hp-out
3895 * AD1984A = AD1884A + digital-mic
3896 * AD1883 = equivalent with AD1984A
3897 * AD1984B = AD1984A + extra SPDIF-out
3900 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3903 static const hda_nid_t ad1884a_dac_nids[1] = {
3907 #define ad1884a_adc_nids ad1884_adc_nids
3908 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3910 #define AD1884A_SPDIF_OUT 0x02
3912 static const struct hda_input_mux ad1884a_capture_source = {
3915 { "Front Mic", 0x0 },
3923 static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
3924 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3925 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3926 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3927 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3928 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3929 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3930 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3931 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3932 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3933 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3934 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3935 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3936 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3937 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3938 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3939 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3940 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3941 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
3942 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3943 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3944 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3945 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3946 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3948 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3949 /* The multiple "Capture Source" controls confuse alsamixer
3950 * So call somewhat different..
3952 /* .name = "Capture Source", */
3953 .name = "Input Source",
3955 .info = ad198x_mux_enum_info,
3956 .get = ad198x_mux_enum_get,
3957 .put = ad198x_mux_enum_put,
3959 /* SPDIF controls */
3960 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3962 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3963 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3964 /* identical with ad1983 */
3965 .info = ad1983_spdif_route_info,
3966 .get = ad1983_spdif_route_get,
3967 .put = ad1983_spdif_route_put,
3973 * initialization verbs
3975 static const struct hda_verb ad1884a_init_verbs[] = {
3976 /* DACs; unmute as default */
3977 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3978 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3979 /* Port-A (HP) mixer - route only from analog mixer */
3980 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3981 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3983 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3984 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3985 /* Port-D (Line-out) mixer - route only from analog mixer */
3986 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3987 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3989 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3990 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3991 /* Mono-out mixer - route only from analog mixer */
3992 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3993 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3995 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3996 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3997 /* Port-B (front mic) pin */
3998 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3999 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4000 /* Port-C (rear line-in) pin */
4001 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4002 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4003 /* Port-E (rear mic) pin */
4004 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4005 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4006 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
4007 /* Port-F (CD) pin */
4008 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4009 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4010 /* Analog mixer; mute as default */
4011 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4012 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4013 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4014 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4015 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
4016 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4017 /* Analog Mix output amp */
4018 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4019 /* capture sources */
4020 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
4021 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4022 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4023 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4024 /* SPDIF output amp */
4025 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4029 #ifdef CONFIG_SND_HDA_POWER_SAVE
4030 static const struct hda_amp_list ad1884a_loopbacks[] = {
4031 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4032 { 0x20, HDA_INPUT, 1 }, /* Mic */
4033 { 0x20, HDA_INPUT, 2 }, /* CD */
4034 { 0x20, HDA_INPUT, 4 }, /* Docking */
4042 * Port A: Headphone jack
4044 * Port C: Internal MIC
4045 * Port D: Dock Line Out (if enabled)
4046 * Port E: Dock Line In (if enabled)
4047 * Port F: Internal speakers
4050 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
4051 struct snd_ctl_elem_value *ucontrol)
4053 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4054 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
4055 int mute = (!ucontrol->value.integer.value[0] &&
4056 !ucontrol->value.integer.value[1]);
4057 /* toggle GPIO1 according to the mute state */
4058 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
4063 static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
4064 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4066 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4067 .name = "Master Playback Switch",
4068 .subdevice = HDA_SUBDEV_AMP_FLAG,
4069 .info = snd_hda_mixer_amp_switch_info,
4070 .get = snd_hda_mixer_amp_switch_get,
4071 .put = ad1884a_mobile_master_sw_put,
4072 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4074 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4075 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4076 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4077 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4078 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4079 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4080 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4081 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4082 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4083 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4084 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4085 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4086 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4087 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4091 static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
4092 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4093 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4095 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4096 .name = "Master Playback Switch",
4097 .subdevice = HDA_SUBDEV_AMP_FLAG,
4098 .info = snd_hda_mixer_amp_switch_info,
4099 .get = snd_hda_mixer_amp_switch_get,
4100 .put = ad1884a_mobile_master_sw_put,
4101 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4103 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4104 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4105 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
4106 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
4107 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4108 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4112 /* mute internal speaker if HP is plugged */
4113 static void ad1884a_hp_automute(struct hda_codec *codec)
4115 unsigned int present;
4117 present = snd_hda_jack_detect(codec, 0x11);
4118 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4119 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4120 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4121 present ? 0x00 : 0x02);
4124 /* switch to external mic if plugged */
4125 static void ad1884a_hp_automic(struct hda_codec *codec)
4127 unsigned int present;
4129 present = snd_hda_jack_detect(codec, 0x14);
4130 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4134 #define AD1884A_HP_EVENT 0x37
4135 #define AD1884A_MIC_EVENT 0x36
4137 /* unsolicited event for HP jack sensing */
4138 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4140 switch (res >> 26) {
4141 case AD1884A_HP_EVENT:
4142 ad1884a_hp_automute(codec);
4144 case AD1884A_MIC_EVENT:
4145 ad1884a_hp_automic(codec);
4150 /* initialize jack-sensing, too */
4151 static int ad1884a_hp_init(struct hda_codec *codec)
4154 ad1884a_hp_automute(codec);
4155 ad1884a_hp_automic(codec);
4159 /* mute internal speaker if HP or docking HP is plugged */
4160 static void ad1884a_laptop_automute(struct hda_codec *codec)
4162 unsigned int present;
4164 present = snd_hda_jack_detect(codec, 0x11);
4166 present = snd_hda_jack_detect(codec, 0x12);
4167 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4168 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4169 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4170 present ? 0x00 : 0x02);
4173 /* switch to external mic if plugged */
4174 static void ad1884a_laptop_automic(struct hda_codec *codec)
4178 if (snd_hda_jack_detect(codec, 0x14))
4180 else if (snd_hda_jack_detect(codec, 0x1c))
4184 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4187 /* unsolicited event for HP jack sensing */
4188 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4191 switch (res >> 26) {
4192 case AD1884A_HP_EVENT:
4193 ad1884a_laptop_automute(codec);
4195 case AD1884A_MIC_EVENT:
4196 ad1884a_laptop_automic(codec);
4201 /* initialize jack-sensing, too */
4202 static int ad1884a_laptop_init(struct hda_codec *codec)
4205 ad1884a_laptop_automute(codec);
4206 ad1884a_laptop_automic(codec);
4210 /* additional verbs for laptop model */
4211 static const struct hda_verb ad1884a_laptop_verbs[] = {
4212 /* Port-A (HP) pin - always unmuted */
4213 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4214 /* Port-F (int speaker) mixer - route only from analog mixer */
4215 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4216 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4217 /* Port-F (int speaker) pin */
4218 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4219 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4220 /* required for compaq 6530s/6531s speaker output */
4221 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4222 /* Port-C pin - internal mic-in */
4223 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4224 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4225 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4226 /* Port-D (docking line-out) pin - default unmuted */
4227 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4229 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4230 /* unsolicited event for pin-sense */
4231 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4232 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4233 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4234 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4235 /* allow to touch GPIO1 (for mute control) */
4236 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4237 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4238 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4242 static const struct hda_verb ad1884a_mobile_verbs[] = {
4243 /* DACs; unmute as default */
4244 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4245 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4246 /* Port-A (HP) mixer - route only from analog mixer */
4247 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4248 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4250 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4251 /* Port-A (HP) pin - always unmuted */
4252 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4253 /* Port-B (mic jack) pin */
4254 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4255 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4256 /* Port-C (int mic) pin */
4257 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4258 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4259 /* Port-F (int speaker) mixer - route only from analog mixer */
4260 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4261 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4263 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4264 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4265 /* Analog mixer; mute as default */
4266 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4267 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4268 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4269 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4270 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4271 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4272 /* Analog Mix output amp */
4273 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4274 /* capture sources */
4275 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4276 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4277 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4278 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4279 /* unsolicited event for pin-sense */
4280 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4281 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4282 /* allow to touch GPIO1 (for mute control) */
4283 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4284 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4285 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4294 * 0x17 - built-in mic
4297 static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4299 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4301 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4303 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4304 /* unsolicited event for pin-sense */
4305 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4306 /* internal mic - dmic */
4307 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4308 /* set magic COEFs for dmic */
4309 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4310 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4314 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4315 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4316 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4317 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4318 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4319 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4320 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4321 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4322 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4323 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4324 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4326 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4327 .name = "Capture Source",
4328 .info = ad198x_mux_enum_info,
4329 .get = ad198x_mux_enum_get,
4330 .put = ad198x_mux_enum_put,
4335 static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4339 { "Internal Mic", 0x5 },
4344 /* mute internal speaker if HP is plugged */
4345 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4347 unsigned int present;
4349 present = snd_hda_jack_detect(codec, 0x11);
4350 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4351 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4354 /* unsolicited event for HP jack sensing */
4355 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4358 if ((res >> 26) != AD1884A_HP_EVENT)
4360 ad1984a_thinkpad_automute(codec);
4363 /* initialize jack-sensing, too */
4364 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4367 ad1984a_thinkpad_automute(codec);
4373 * 0x12 - HP/line-out
4374 * 0x13 - speaker (mono)
4378 static const struct hda_verb ad1984a_precision_verbs[] = {
4379 /* Unmute main output path */
4380 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4381 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4382 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4383 /* Analog mixer; mute as default */
4384 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4385 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4388 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4389 /* Select mic as input */
4390 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4391 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4392 /* Configure as mic */
4393 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4394 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4396 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4398 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4399 /* unsolicited event for pin-sense */
4400 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4404 static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4405 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4406 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4407 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4408 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4409 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4410 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4411 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4412 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4413 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4414 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4415 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4420 /* mute internal speaker if HP is plugged */
4421 static void ad1984a_precision_automute(struct hda_codec *codec)
4423 unsigned int present;
4425 present = snd_hda_jack_detect(codec, 0x12);
4426 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4427 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4431 /* unsolicited event for HP jack sensing */
4432 static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4435 if ((res >> 26) != AD1884A_HP_EVENT)
4437 ad1984a_precision_automute(codec);
4440 /* initialize jack-sensing, too */
4441 static int ad1984a_precision_init(struct hda_codec *codec)
4444 ad1984a_precision_automute(codec);
4451 * port-A (0x11) - front hp-out
4452 * port-B (0x14) - unused
4453 * port-C (0x15) - unused
4454 * port-D (0x12) - rear line out
4455 * port-E (0x1c) - front mic-in
4456 * port-F (0x16) - Internal speakers
4457 * digital-mic (0x17) - Internal mic
4460 static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4461 /* DACs; unmute as default */
4462 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4463 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4464 /* Port-A (HP) mixer - route only from analog mixer */
4465 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4466 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4468 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4469 /* Port-A (HP) pin - always unmuted */
4470 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4471 /* Port-E (int speaker) mixer - route only from analog mixer */
4472 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4474 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4475 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4476 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4477 /* Port-F (int speaker) mixer - route only from analog mixer */
4478 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4479 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4481 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4482 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4483 /* Analog mixer; mute as default */
4484 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4485 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4486 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4487 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4488 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4489 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4490 /* Analog Mix output amp */
4491 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4492 /* capture sources */
4493 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4494 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4495 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4496 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4497 /* unsolicited event for pin-sense */
4498 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4499 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4500 /* allow to touch GPIO1 (for mute control) */
4501 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4502 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4503 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4504 /* internal mic - dmic */
4505 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4506 /* set magic COEFs for dmic */
4507 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4508 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4512 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4513 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4514 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4517 .subdevice = HDA_SUBDEV_AMP_FLAG,
4518 .name = "Master Playback Switch",
4519 .info = snd_hda_mixer_amp_switch_info,
4520 .get = snd_hda_mixer_amp_switch_get,
4521 .put = ad1884a_mobile_master_sw_put,
4522 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4524 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4525 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4526 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4527 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4528 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4529 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4533 /* switch to external mic if plugged */
4534 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4536 if (snd_hda_jack_detect(codec, 0x1c))
4537 snd_hda_codec_write(codec, 0x0c, 0,
4538 AC_VERB_SET_CONNECT_SEL, 0x4);
4540 snd_hda_codec_write(codec, 0x0c, 0,
4541 AC_VERB_SET_CONNECT_SEL, 0x5);
4545 /* unsolicited event for HP jack sensing */
4546 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4549 switch (res >> 26) {
4550 case AD1884A_HP_EVENT:
4551 ad1884a_hp_automute(codec);
4553 case AD1884A_MIC_EVENT:
4554 ad1984a_touchsmart_automic(codec);
4559 /* initialize jack-sensing, too */
4560 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4563 ad1884a_hp_automute(codec);
4564 ad1984a_touchsmart_automic(codec);
4582 static const char * const ad1884a_models[AD1884A_MODELS] = {
4583 [AD1884A_DESKTOP] = "desktop",
4584 [AD1884A_LAPTOP] = "laptop",
4585 [AD1884A_MOBILE] = "mobile",
4586 [AD1884A_THINKPAD] = "thinkpad",
4587 [AD1984A_TOUCHSMART] = "touchsmart",
4588 [AD1984A_PRECISION] = "precision",
4591 static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4592 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4593 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4594 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4595 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4596 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4597 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4598 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4599 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4600 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4601 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4602 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4606 static int patch_ad1884a(struct hda_codec *codec)
4608 struct ad198x_spec *spec;
4609 int err, board_config;
4611 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4617 err = snd_hda_attach_beep_device(codec, 0x10);
4622 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4624 spec->multiout.max_channels = 2;
4625 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4626 spec->multiout.dac_nids = ad1884a_dac_nids;
4627 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4628 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4629 spec->adc_nids = ad1884a_adc_nids;
4630 spec->capsrc_nids = ad1884a_capsrc_nids;
4631 spec->input_mux = &ad1884a_capture_source;
4632 spec->num_mixers = 1;
4633 spec->mixers[0] = ad1884a_base_mixers;
4634 spec->num_init_verbs = 1;
4635 spec->init_verbs[0] = ad1884a_init_verbs;
4636 spec->spdif_route = 0;
4637 #ifdef CONFIG_SND_HDA_POWER_SAVE
4638 spec->loopback.amplist = ad1884a_loopbacks;
4640 codec->patch_ops = ad198x_patch_ops;
4642 /* override some parameters */
4643 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4646 switch (board_config) {
4647 case AD1884A_LAPTOP:
4648 spec->mixers[0] = ad1884a_laptop_mixers;
4649 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4650 spec->multiout.dig_out_nid = 0;
4651 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4652 codec->patch_ops.init = ad1884a_laptop_init;
4653 /* set the upper-limit for mixer amp to 0dB for avoiding the
4654 * possible damage by overloading
4656 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4657 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4658 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4659 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4660 (1 << AC_AMPCAP_MUTE_SHIFT));
4662 case AD1884A_MOBILE:
4663 spec->mixers[0] = ad1884a_mobile_mixers;
4664 spec->init_verbs[0] = ad1884a_mobile_verbs;
4665 spec->multiout.dig_out_nid = 0;
4666 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4667 codec->patch_ops.init = ad1884a_hp_init;
4668 /* set the upper-limit for mixer amp to 0dB for avoiding the
4669 * possible damage by overloading
4671 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4672 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4673 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4674 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4675 (1 << AC_AMPCAP_MUTE_SHIFT));
4677 case AD1884A_THINKPAD:
4678 spec->mixers[0] = ad1984a_thinkpad_mixers;
4679 spec->init_verbs[spec->num_init_verbs++] =
4680 ad1984a_thinkpad_verbs;
4681 spec->multiout.dig_out_nid = 0;
4682 spec->input_mux = &ad1984a_thinkpad_capture_source;
4683 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4684 codec->patch_ops.init = ad1984a_thinkpad_init;
4686 case AD1984A_PRECISION:
4687 spec->mixers[0] = ad1984a_precision_mixers;
4688 spec->init_verbs[spec->num_init_verbs++] =
4689 ad1984a_precision_verbs;
4690 spec->multiout.dig_out_nid = 0;
4691 codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4692 codec->patch_ops.init = ad1984a_precision_init;
4694 case AD1984A_TOUCHSMART:
4695 spec->mixers[0] = ad1984a_touchsmart_mixers;
4696 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4697 spec->multiout.dig_out_nid = 0;
4698 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4699 codec->patch_ops.init = ad1984a_touchsmart_init;
4700 /* set the upper-limit for mixer amp to 0dB for avoiding the
4701 * possible damage by overloading
4703 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4704 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4705 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4706 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4707 (1 << AC_AMPCAP_MUTE_SHIFT));
4711 codec->no_trigger_sense = 1;
4712 codec->no_sticky_stream = 1;
4721 * port-A - front hp-out
4722 * port-B - front mic-in
4723 * port-C - rear line-in, shared surr-out (3stack)
4724 * port-D - rear line-out
4725 * port-E - rear mic-in, shared clfe-out (3stack)
4726 * port-F - rear surr-out (6stack)
4727 * port-G - rear clfe-out (6stack)
4730 static const hda_nid_t ad1882_dac_nids[3] = {
4734 static const hda_nid_t ad1882_adc_nids[2] = {
4738 static const hda_nid_t ad1882_capsrc_nids[2] = {
4742 #define AD1882_SPDIF_OUT 0x02
4744 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4745 static const struct hda_input_mux ad1882_capture_source = {
4748 { "Front Mic", 0x1 },
4756 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4757 static const struct hda_input_mux ad1882a_capture_source = {
4760 { "Front Mic", 0x1 },
4763 { "Digital Mic", 0x06 },
4768 static const struct snd_kcontrol_new ad1882_base_mixers[] = {
4769 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4770 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4771 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4772 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4773 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4774 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4775 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4776 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4778 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
4779 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
4780 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
4781 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4782 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4783 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4784 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4786 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4787 /* The multiple "Capture Source" controls confuse alsamixer
4788 * So call somewhat different..
4790 /* .name = "Capture Source", */
4791 .name = "Input Source",
4793 .info = ad198x_mux_enum_info,
4794 .get = ad198x_mux_enum_get,
4795 .put = ad198x_mux_enum_put,
4797 /* SPDIF controls */
4798 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4800 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4801 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4802 /* identical with ad1983 */
4803 .info = ad1983_spdif_route_info,
4804 .get = ad1983_spdif_route_get,
4805 .put = ad1983_spdif_route_put,
4810 static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4811 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4812 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4813 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4814 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4815 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4816 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4817 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4818 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4822 static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4823 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4824 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4825 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4826 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4827 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4828 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4829 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4830 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4831 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
4835 static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4836 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4837 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4838 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4840 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4841 .name = "Channel Mode",
4842 .info = ad198x_ch_mode_info,
4843 .get = ad198x_ch_mode_get,
4844 .put = ad198x_ch_mode_put,
4849 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4850 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4851 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4852 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4856 static const struct hda_verb ad1882_ch2_init[] = {
4857 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4858 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4859 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4860 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4861 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4862 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4866 static const struct hda_verb ad1882_ch4_init[] = {
4867 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4868 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4869 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4870 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4871 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4872 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4876 static const struct hda_verb ad1882_ch6_init[] = {
4877 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4878 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4879 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4880 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4881 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4882 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4886 static const struct hda_channel_mode ad1882_modes[3] = {
4887 { 2, ad1882_ch2_init },
4888 { 4, ad1882_ch4_init },
4889 { 6, ad1882_ch6_init },
4893 * initialization verbs
4895 static const struct hda_verb ad1882_init_verbs[] = {
4896 /* DACs; mute as default */
4897 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4898 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4899 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4900 /* Port-A (HP) mixer */
4901 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4902 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4904 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4905 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4906 /* HP selector - select DAC2 */
4907 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4908 /* Port-D (Line-out) mixer */
4909 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4910 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4912 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4913 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4914 /* Mono-out mixer */
4915 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4916 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4918 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4919 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4920 /* Port-B (front mic) pin */
4921 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4922 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4923 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4924 /* Port-C (line-in) pin */
4925 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4926 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4927 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4928 /* Port-C mixer - mute as input */
4929 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4930 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4931 /* Port-E (mic-in) pin */
4932 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4933 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4934 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4935 /* Port-E mixer - mute as input */
4936 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4937 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4938 /* Port-F (surround) */
4939 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4940 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4942 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4943 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4944 /* Analog mixer; mute as default */
4945 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4946 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4947 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4948 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4949 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4950 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4951 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4952 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4953 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4954 /* Analog Mix output amp */
4955 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4956 /* SPDIF output selector */
4957 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4958 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4959 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4963 #ifdef CONFIG_SND_HDA_POWER_SAVE
4964 static const struct hda_amp_list ad1882_loopbacks[] = {
4965 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4966 { 0x20, HDA_INPUT, 1 }, /* Mic */
4967 { 0x20, HDA_INPUT, 4 }, /* Line */
4968 { 0x20, HDA_INPUT, 6 }, /* CD */
4980 static const char * const ad1882_models[AD1986A_MODELS] = {
4981 [AD1882_3STACK] = "3stack",
4982 [AD1882_6STACK] = "6stack",
4986 static int patch_ad1882(struct hda_codec *codec)
4988 struct ad198x_spec *spec;
4989 int err, board_config;
4991 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4997 err = snd_hda_attach_beep_device(codec, 0x10);
5002 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
5004 spec->multiout.max_channels = 6;
5005 spec->multiout.num_dacs = 3;
5006 spec->multiout.dac_nids = ad1882_dac_nids;
5007 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
5008 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
5009 spec->adc_nids = ad1882_adc_nids;
5010 spec->capsrc_nids = ad1882_capsrc_nids;
5011 if (codec->vendor_id == 0x11d41882)
5012 spec->input_mux = &ad1882_capture_source;
5014 spec->input_mux = &ad1882a_capture_source;
5015 spec->num_mixers = 2;
5016 spec->mixers[0] = ad1882_base_mixers;
5017 if (codec->vendor_id == 0x11d41882)
5018 spec->mixers[1] = ad1882_loopback_mixers;
5020 spec->mixers[1] = ad1882a_loopback_mixers;
5021 spec->num_init_verbs = 1;
5022 spec->init_verbs[0] = ad1882_init_verbs;
5023 spec->spdif_route = 0;
5024 #ifdef CONFIG_SND_HDA_POWER_SAVE
5025 spec->loopback.amplist = ad1882_loopbacks;
5027 spec->vmaster_nid = 0x04;
5029 codec->patch_ops = ad198x_patch_ops;
5031 /* override some parameters */
5032 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
5033 ad1882_models, NULL);
5034 switch (board_config) {
5037 spec->num_mixers = 3;
5038 spec->mixers[2] = ad1882_3stack_mixers;
5039 spec->channel_mode = ad1882_modes;
5040 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
5041 spec->need_dac_fix = 1;
5042 spec->multiout.max_channels = 2;
5043 spec->multiout.num_dacs = 1;
5046 spec->num_mixers = 3;
5047 spec->mixers[2] = ad1882_6stack_mixers;
5051 codec->no_trigger_sense = 1;
5052 codec->no_sticky_stream = 1;
5061 static const struct hda_codec_preset snd_hda_preset_analog[] = {
5062 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
5063 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
5064 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
5065 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
5066 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
5067 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
5068 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
5069 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
5070 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
5071 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
5072 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
5073 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
5074 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
5075 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
5076 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
5080 MODULE_ALIAS("snd-hda-codec-id:11d4*");
5082 MODULE_LICENSE("GPL");
5083 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
5085 static struct hda_codec_preset_list analog_list = {
5086 .preset = snd_hda_preset_analog,
5087 .owner = THIS_MODULE,
5090 static int __init patch_analog_init(void)
5092 return snd_hda_add_codec_preset(&analog_list);
5095 static void __exit patch_analog_exit(void)
5097 snd_hda_delete_codec_preset(&analog_list);
5100 module_init(patch_analog_init)
5101 module_exit(patch_analog_exit)