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 struct snd_kcontrol_new *mixers[5];
35 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb *init_verbs[5]; /* 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;
50 unsigned int num_adc_nids;
52 hda_nid_t dig_in_nid; /* digital-in NID; optional */
55 const struct hda_input_mux *input_mux;
56 hda_nid_t *capsrc_nids;
57 unsigned int cur_mux[3];
60 const struct hda_channel_mode *channel_mode;
64 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
66 unsigned int spdif_route;
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg;
70 struct snd_array kctls;
71 struct hda_input_mux private_imux;
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
74 unsigned int jack_present: 1;
75 unsigned int inv_jack_detect: 1;/* inverted jack-detection */
76 unsigned int inv_eapd: 1; /* inverted EAPD implementation */
77 unsigned int analog_beep: 1; /* analog beep input present */
79 #ifdef CONFIG_SND_HDA_POWER_SAVE
80 struct hda_loopback_check loopback;
82 /* for virtual master */
83 hda_nid_t vmaster_nid;
84 const char **slave_vols;
85 const char **slave_sws;
89 * input MUX handling (common part)
91 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
93 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
94 struct ad198x_spec *spec = codec->spec;
96 return snd_hda_input_mux_info(spec->input_mux, uinfo);
99 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
101 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
102 struct ad198x_spec *spec = codec->spec;
103 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
105 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
109 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
111 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
112 struct ad198x_spec *spec = codec->spec;
113 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
115 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
116 spec->capsrc_nids[adc_idx],
117 &spec->cur_mux[adc_idx]);
121 * initialization (common callbacks)
123 static int ad198x_init(struct hda_codec *codec)
125 struct ad198x_spec *spec = codec->spec;
128 for (i = 0; i < spec->num_init_verbs; i++)
129 snd_hda_sequence_write(codec, spec->init_verbs[i]);
133 static const char *ad_slave_vols[] = {
134 "Front Playback Volume",
135 "Surround Playback Volume",
136 "Center Playback Volume",
137 "LFE Playback Volume",
138 "Side Playback Volume",
139 "Headphone Playback Volume",
140 "Mono Playback Volume",
141 "Speaker Playback Volume",
142 "IEC958 Playback Volume",
146 static const char *ad_slave_sws[] = {
147 "Front Playback Switch",
148 "Surround Playback Switch",
149 "Center Playback Switch",
150 "LFE Playback Switch",
151 "Side Playback Switch",
152 "Headphone Playback Switch",
153 "Mono Playback Switch",
154 "Speaker Playback Switch",
155 "IEC958 Playback Switch",
159 static void ad198x_free_kctls(struct hda_codec *codec);
161 #ifdef CONFIG_SND_HDA_INPUT_BEEP
162 /* additional beep mixers; the actual parameters are overwritten at build */
163 static struct snd_kcontrol_new ad_beep_mixer[] = {
164 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
165 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
169 static struct snd_kcontrol_new ad_beep2_mixer[] = {
170 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
171 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
175 #define set_beep_amp(spec, nid, idx, dir) \
176 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
178 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
181 static int ad198x_build_controls(struct hda_codec *codec)
183 struct ad198x_spec *spec = codec->spec;
184 struct snd_kcontrol *kctl;
188 for (i = 0; i < spec->num_mixers; i++) {
189 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
193 if (spec->multiout.dig_out_nid) {
194 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
197 err = snd_hda_create_spdif_share_sw(codec,
201 spec->multiout.share_spdif = 1;
203 if (spec->dig_in_nid) {
204 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
209 /* create beep controls if needed */
210 #ifdef CONFIG_SND_HDA_INPUT_BEEP
211 if (spec->beep_amp) {
212 struct snd_kcontrol_new *knew;
213 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
214 for ( ; knew->name; knew++) {
215 struct snd_kcontrol *kctl;
216 kctl = snd_ctl_new1(knew, codec);
219 kctl->private_value = spec->beep_amp;
220 err = snd_hda_ctl_add(codec, 0, kctl);
227 /* if we have no master control, let's create it */
228 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
229 unsigned int vmaster_tlv[4];
230 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
231 HDA_OUTPUT, vmaster_tlv);
232 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
235 spec->slave_vols : ad_slave_vols));
239 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
240 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
243 spec->slave_sws : ad_slave_sws));
248 ad198x_free_kctls(codec); /* no longer needed */
250 /* assign Capture Source enums to NID */
251 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
253 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
254 for (i = 0; kctl && i < kctl->count; i++) {
255 err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
260 /* assign IEC958 enums to NID */
261 kctl = snd_hda_find_mixer_ctl(codec,
262 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
264 err = snd_hda_add_nid(codec, kctl, 0,
265 spec->multiout.dig_out_nid);
273 #ifdef CONFIG_SND_HDA_POWER_SAVE
274 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
276 struct ad198x_spec *spec = codec->spec;
277 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
282 * Analog playback callbacks
284 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
285 struct hda_codec *codec,
286 struct snd_pcm_substream *substream)
288 struct ad198x_spec *spec = codec->spec;
289 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
293 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
294 struct hda_codec *codec,
295 unsigned int stream_tag,
297 struct snd_pcm_substream *substream)
299 struct ad198x_spec *spec = codec->spec;
300 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
304 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
305 struct hda_codec *codec,
306 struct snd_pcm_substream *substream)
308 struct ad198x_spec *spec = codec->spec;
309 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
315 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
316 struct hda_codec *codec,
317 struct snd_pcm_substream *substream)
319 struct ad198x_spec *spec = codec->spec;
320 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
323 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
324 struct hda_codec *codec,
325 struct snd_pcm_substream *substream)
327 struct ad198x_spec *spec = codec->spec;
328 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
331 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
332 struct hda_codec *codec,
333 unsigned int stream_tag,
335 struct snd_pcm_substream *substream)
337 struct ad198x_spec *spec = codec->spec;
338 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
342 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
343 struct hda_codec *codec,
344 struct snd_pcm_substream *substream)
346 struct ad198x_spec *spec = codec->spec;
347 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
353 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
354 struct hda_codec *codec,
355 unsigned int stream_tag,
357 struct snd_pcm_substream *substream)
359 struct ad198x_spec *spec = codec->spec;
360 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
361 stream_tag, 0, format);
365 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
366 struct hda_codec *codec,
367 struct snd_pcm_substream *substream)
369 struct ad198x_spec *spec = codec->spec;
370 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
377 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
380 .channels_max = 6, /* changed later */
381 .nid = 0, /* fill later */
383 .open = ad198x_playback_pcm_open,
384 .prepare = ad198x_playback_pcm_prepare,
385 .cleanup = ad198x_playback_pcm_cleanup
389 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
393 .nid = 0, /* fill later */
395 .prepare = ad198x_capture_pcm_prepare,
396 .cleanup = ad198x_capture_pcm_cleanup
400 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
404 .nid = 0, /* fill later */
406 .open = ad198x_dig_playback_pcm_open,
407 .close = ad198x_dig_playback_pcm_close,
408 .prepare = ad198x_dig_playback_pcm_prepare,
409 .cleanup = ad198x_dig_playback_pcm_cleanup
413 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
417 /* NID is set in alc_build_pcms */
420 static int ad198x_build_pcms(struct hda_codec *codec)
422 struct ad198x_spec *spec = codec->spec;
423 struct hda_pcm *info = spec->pcm_rec;
426 codec->pcm_info = info;
428 info->name = "AD198x Analog";
429 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
430 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
431 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
432 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
433 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
434 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
436 if (spec->multiout.dig_out_nid) {
439 info->name = "AD198x Digital";
440 info->pcm_type = HDA_PCM_TYPE_SPDIF;
441 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
442 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
443 if (spec->dig_in_nid) {
444 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
445 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
452 static inline void ad198x_shutup(struct hda_codec *codec)
454 snd_hda_shutup_pins(codec);
457 static void ad198x_free_kctls(struct hda_codec *codec)
459 struct ad198x_spec *spec = codec->spec;
461 if (spec->kctls.list) {
462 struct snd_kcontrol_new *kctl = spec->kctls.list;
464 for (i = 0; i < spec->kctls.used; i++)
467 snd_array_free(&spec->kctls);
470 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
473 struct ad198x_spec *spec = codec->spec;
474 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
475 !spec->inv_eapd ? 0x00 : 0x02);
476 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
477 !spec->inv_eapd ? 0x00 : 0x02);
480 static void ad198x_power_eapd(struct hda_codec *codec)
482 /* We currently only handle front, HP */
483 switch (codec->vendor_id) {
492 ad198x_power_eapd_write(codec, 0x12, 0x11);
496 ad198x_power_eapd_write(codec, 0x05, 0x06);
499 ad198x_power_eapd_write(codec, 0x1b, 0x1a);
505 ad198x_power_eapd_write(codec, 0x29, 0x22);
510 static void ad198x_free(struct hda_codec *codec)
512 struct ad198x_spec *spec = codec->spec;
517 ad198x_shutup(codec);
518 ad198x_free_kctls(codec);
520 snd_hda_detach_beep_device(codec);
523 #ifdef SND_HDA_NEEDS_RESUME
524 static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
526 ad198x_shutup(codec);
527 ad198x_power_eapd(codec);
531 static int ad198x_resume(struct hda_codec *codec)
534 snd_hda_codec_resume_amp(codec);
535 snd_hda_codec_resume_cache(codec);
540 static struct hda_codec_ops ad198x_patch_ops = {
541 .build_controls = ad198x_build_controls,
542 .build_pcms = ad198x_build_pcms,
545 #ifdef CONFIG_SND_HDA_POWER_SAVE
546 .check_power_status = ad198x_check_power_status,
548 #ifdef SND_HDA_NEEDS_RESUME
549 .suspend = ad198x_suspend,
550 .resume = ad198x_resume,
552 .reboot_notify = ad198x_shutup,
558 * the private value = nid
560 #define ad198x_eapd_info snd_ctl_boolean_mono_info
562 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
563 struct snd_ctl_elem_value *ucontrol)
565 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
566 struct ad198x_spec *spec = codec->spec;
568 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
570 ucontrol->value.integer.value[0] = spec->cur_eapd;
574 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
575 struct snd_ctl_elem_value *ucontrol)
577 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
578 struct ad198x_spec *spec = codec->spec;
579 hda_nid_t nid = kcontrol->private_value & 0xff;
581 eapd = !!ucontrol->value.integer.value[0];
584 if (eapd == spec->cur_eapd)
586 spec->cur_eapd = eapd;
587 snd_hda_codec_write_cache(codec, nid,
588 0, AC_VERB_SET_EAPD_BTLENABLE,
593 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
594 struct snd_ctl_elem_info *uinfo);
595 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
596 struct snd_ctl_elem_value *ucontrol);
597 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
598 struct snd_ctl_elem_value *ucontrol);
605 #define AD1986A_SPDIF_OUT 0x02
606 #define AD1986A_FRONT_DAC 0x03
607 #define AD1986A_SURR_DAC 0x04
608 #define AD1986A_CLFE_DAC 0x05
609 #define AD1986A_ADC 0x06
611 static hda_nid_t ad1986a_dac_nids[3] = {
612 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
614 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
615 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
617 static struct hda_input_mux ad1986a_capture_source = {
631 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
632 .ops = &snd_hda_bind_vol,
634 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
635 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
636 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
641 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
642 .ops = &snd_hda_bind_sw,
644 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
645 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
646 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
654 static struct snd_kcontrol_new ad1986a_mixers[] = {
656 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
658 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
659 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
660 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
661 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
662 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
665 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
666 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
667 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
668 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
669 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
670 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
671 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
672 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
673 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
674 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
675 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
676 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
677 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
678 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
679 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
680 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
681 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
682 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
684 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
685 .name = "Capture Source",
686 .info = ad198x_mux_enum_info,
687 .get = ad198x_mux_enum_get,
688 .put = ad198x_mux_enum_put,
690 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
694 /* additional mixers for 3stack mode */
695 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
697 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
698 .name = "Channel Mode",
699 .info = ad198x_ch_mode_info,
700 .get = ad198x_ch_mode_get,
701 .put = ad198x_ch_mode_put,
706 /* laptop model - 2ch only */
707 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
709 /* master controls both pins 0x1a and 0x1b */
710 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
711 .ops = &snd_hda_bind_vol,
713 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
714 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
719 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
720 .ops = &snd_hda_bind_sw,
722 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
723 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
728 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
729 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
730 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
731 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
732 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
733 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
734 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
735 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
736 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
737 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
738 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
739 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
740 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
741 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
743 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
744 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
745 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
746 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
749 .name = "Capture Source",
750 .info = ad198x_mux_enum_info,
751 .get = ad198x_mux_enum_get,
752 .put = ad198x_mux_enum_put,
757 /* laptop-eapd model - 2ch only */
759 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
763 { "Internal Mic", 0x4 },
768 static struct hda_input_mux ad1986a_automic_capture_source = {
776 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
777 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
778 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
782 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
783 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
784 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
785 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
786 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
787 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
788 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
789 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
791 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
792 .name = "Capture Source",
793 .info = ad198x_mux_enum_info,
794 .get = ad198x_mux_enum_get,
795 .put = ad198x_mux_enum_put,
798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
799 .name = "External Amplifier",
800 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
801 .info = ad198x_eapd_info,
802 .get = ad198x_eapd_get,
803 .put = ad198x_eapd_put,
804 .private_value = 0x1b, /* port-D */
809 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
810 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
811 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
815 /* re-connect the mic boost input according to the jack sensing */
816 static void ad1986a_automic(struct hda_codec *codec)
818 unsigned int present;
819 present = snd_hda_jack_detect(codec, 0x1f);
820 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
821 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
825 #define AD1986A_MIC_EVENT 0x36
827 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
830 if ((res >> 26) != AD1986A_MIC_EVENT)
832 ad1986a_automic(codec);
835 static int ad1986a_automic_init(struct hda_codec *codec)
838 ad1986a_automic(codec);
842 /* laptop-automute - 2ch only */
844 static void ad1986a_update_hp(struct hda_codec *codec)
846 struct ad198x_spec *spec = codec->spec;
849 if (spec->jack_present)
850 mute = HDA_AMP_MUTE; /* mute internal speaker */
852 /* unmute internal speaker if necessary */
853 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
854 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
858 static void ad1986a_hp_automute(struct hda_codec *codec)
860 struct ad198x_spec *spec = codec->spec;
862 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
863 if (spec->inv_jack_detect)
864 spec->jack_present = !spec->jack_present;
865 ad1986a_update_hp(codec);
868 #define AD1986A_HP_EVENT 0x37
870 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
872 if ((res >> 26) != AD1986A_HP_EVENT)
874 ad1986a_hp_automute(codec);
877 static int ad1986a_hp_init(struct hda_codec *codec)
880 ad1986a_hp_automute(codec);
884 /* bind hp and internal speaker mute (with plug check) */
885 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
886 struct snd_ctl_elem_value *ucontrol)
888 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
889 long *valp = ucontrol->value.integer.value;
892 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
894 valp[0] ? 0 : HDA_AMP_MUTE);
895 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
897 valp[1] ? 0 : HDA_AMP_MUTE);
899 ad1986a_update_hp(codec);
903 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
904 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
906 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
907 .name = "Master Playback Switch",
908 .subdevice = HDA_SUBDEV_AMP_FLAG,
909 .info = snd_hda_mixer_amp_switch_info,
910 .get = snd_hda_mixer_amp_switch_get,
911 .put = ad1986a_hp_master_sw_put,
912 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
919 * initialization verbs
921 static struct hda_verb ad1986a_init_verbs[] = {
922 /* Front, Surround, CLFE DAC; mute as default */
923 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
924 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
925 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
927 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
928 /* HP, Line-Out, Surround, CLFE selectors */
929 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
930 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
931 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
932 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
934 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
935 /* Mic selector: Mic 1/2 pin */
936 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
937 /* Line-in selector: Line-in */
938 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
940 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
941 /* Record selector: mic */
942 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
943 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
944 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
945 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
946 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
947 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
948 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
950 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
951 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
952 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
953 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
954 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
955 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
956 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
958 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
959 /* Front, Surround, CLFE Pins */
960 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
961 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
962 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
964 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
966 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
967 /* Line, Aux, CD, Beep-In Pin */
968 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
969 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
970 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
971 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
972 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
976 static struct hda_verb ad1986a_ch2_init[] = {
977 /* Surround out -> Line In */
978 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
979 /* Line-in selectors */
980 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
982 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
983 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
984 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
988 static struct hda_verb ad1986a_ch4_init[] = {
989 /* Surround out -> Surround */
990 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
991 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
993 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
994 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
998 static struct hda_verb ad1986a_ch6_init[] = {
999 /* Surround out -> Surround out */
1000 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1001 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1003 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1004 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1008 static struct hda_channel_mode ad1986a_modes[3] = {
1009 { 2, ad1986a_ch2_init },
1010 { 4, ad1986a_ch4_init },
1011 { 6, ad1986a_ch6_init },
1014 /* eapd initialization */
1015 static struct hda_verb ad1986a_eapd_init_verbs[] = {
1016 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1020 static struct hda_verb ad1986a_automic_verbs[] = {
1021 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1022 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1023 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1024 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1025 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1029 /* Ultra initialization */
1030 static struct hda_verb ad1986a_ultra_init[] = {
1031 /* eapd initialization */
1032 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1033 /* CLFE -> Mic in */
1034 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1035 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1036 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1040 /* pin sensing on HP jack */
1041 static struct hda_verb ad1986a_hp_init_verbs[] = {
1042 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1046 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1049 switch (res >> 26) {
1050 case AD1986A_HP_EVENT:
1051 ad1986a_hp_automute(codec);
1053 case AD1986A_MIC_EVENT:
1054 ad1986a_automic(codec);
1059 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1062 ad1986a_hp_automute(codec);
1063 ad1986a_automic(codec);
1073 AD1986A_LAPTOP_EAPD,
1074 AD1986A_LAPTOP_AUTOMUTE,
1077 AD1986A_SAMSUNG_P50,
1081 static const char *ad1986a_models[AD1986A_MODELS] = {
1082 [AD1986A_6STACK] = "6stack",
1083 [AD1986A_3STACK] = "3stack",
1084 [AD1986A_LAPTOP] = "laptop",
1085 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1086 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1087 [AD1986A_ULTRA] = "ultra",
1088 [AD1986A_SAMSUNG] = "samsung",
1089 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1092 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1093 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1094 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1095 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1096 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1097 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1098 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1099 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1100 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1101 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1102 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1103 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1104 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1105 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1106 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1107 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1108 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1109 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1110 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1111 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1112 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1113 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1114 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1115 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1116 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1117 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1118 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1119 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1123 #ifdef CONFIG_SND_HDA_POWER_SAVE
1124 static struct hda_amp_list ad1986a_loopbacks[] = {
1125 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1126 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1127 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1128 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1129 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1134 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1136 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1137 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1140 static int patch_ad1986a(struct hda_codec *codec)
1142 struct ad198x_spec *spec;
1143 int err, board_config;
1145 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1151 err = snd_hda_attach_beep_device(codec, 0x19);
1156 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1158 spec->multiout.max_channels = 6;
1159 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1160 spec->multiout.dac_nids = ad1986a_dac_nids;
1161 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1162 spec->num_adc_nids = 1;
1163 spec->adc_nids = ad1986a_adc_nids;
1164 spec->capsrc_nids = ad1986a_capsrc_nids;
1165 spec->input_mux = &ad1986a_capture_source;
1166 spec->num_mixers = 1;
1167 spec->mixers[0] = ad1986a_mixers;
1168 spec->num_init_verbs = 1;
1169 spec->init_verbs[0] = ad1986a_init_verbs;
1170 #ifdef CONFIG_SND_HDA_POWER_SAVE
1171 spec->loopback.amplist = ad1986a_loopbacks;
1173 spec->vmaster_nid = 0x1b;
1174 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1176 codec->patch_ops = ad198x_patch_ops;
1178 /* override some parameters */
1179 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1182 switch (board_config) {
1183 case AD1986A_3STACK:
1184 spec->num_mixers = 2;
1185 spec->mixers[1] = ad1986a_3st_mixers;
1186 spec->num_init_verbs = 2;
1187 spec->init_verbs[1] = ad1986a_ch2_init;
1188 spec->channel_mode = ad1986a_modes;
1189 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1190 spec->need_dac_fix = 1;
1191 spec->multiout.max_channels = 2;
1192 spec->multiout.num_dacs = 1;
1194 case AD1986A_LAPTOP:
1195 spec->mixers[0] = ad1986a_laptop_mixers;
1196 spec->multiout.max_channels = 2;
1197 spec->multiout.num_dacs = 1;
1198 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1200 case AD1986A_LAPTOP_EAPD:
1201 spec->num_mixers = 3;
1202 spec->mixers[0] = ad1986a_laptop_master_mixers;
1203 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1204 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1205 spec->num_init_verbs = 2;
1206 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1207 spec->multiout.max_channels = 2;
1208 spec->multiout.num_dacs = 1;
1209 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1210 if (!is_jack_available(codec, 0x25))
1211 spec->multiout.dig_out_nid = 0;
1212 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1214 case AD1986A_SAMSUNG:
1215 spec->num_mixers = 2;
1216 spec->mixers[0] = ad1986a_laptop_master_mixers;
1217 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1218 spec->num_init_verbs = 3;
1219 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1220 spec->init_verbs[2] = ad1986a_automic_verbs;
1221 spec->multiout.max_channels = 2;
1222 spec->multiout.num_dacs = 1;
1223 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1224 if (!is_jack_available(codec, 0x25))
1225 spec->multiout.dig_out_nid = 0;
1226 spec->input_mux = &ad1986a_automic_capture_source;
1227 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1228 codec->patch_ops.init = ad1986a_automic_init;
1230 case AD1986A_SAMSUNG_P50:
1231 spec->num_mixers = 2;
1232 spec->mixers[0] = ad1986a_automute_master_mixers;
1233 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1234 spec->num_init_verbs = 4;
1235 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1236 spec->init_verbs[2] = ad1986a_automic_verbs;
1237 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1238 spec->multiout.max_channels = 2;
1239 spec->multiout.num_dacs = 1;
1240 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1241 if (!is_jack_available(codec, 0x25))
1242 spec->multiout.dig_out_nid = 0;
1243 spec->input_mux = &ad1986a_automic_capture_source;
1244 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1245 codec->patch_ops.init = ad1986a_samsung_p50_init;
1247 case AD1986A_LAPTOP_AUTOMUTE:
1248 spec->num_mixers = 3;
1249 spec->mixers[0] = ad1986a_automute_master_mixers;
1250 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1251 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1252 spec->num_init_verbs = 3;
1253 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1254 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1255 spec->multiout.max_channels = 2;
1256 spec->multiout.num_dacs = 1;
1257 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1258 if (!is_jack_available(codec, 0x25))
1259 spec->multiout.dig_out_nid = 0;
1260 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1261 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1262 codec->patch_ops.init = ad1986a_hp_init;
1263 /* Lenovo N100 seems to report the reversed bit
1264 * for HP jack-sensing
1266 spec->inv_jack_detect = 1;
1269 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1270 spec->num_init_verbs = 2;
1271 spec->init_verbs[1] = ad1986a_ultra_init;
1272 spec->multiout.max_channels = 2;
1273 spec->multiout.num_dacs = 1;
1274 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1275 spec->multiout.dig_out_nid = 0;
1279 /* AD1986A has a hardware problem that it can't share a stream
1280 * with multiple output pins. The copy of front to surrounds
1281 * causes noisy or silent outputs at a certain timing, e.g.
1282 * changing the volume.
1283 * So, let's disable the shared stream.
1285 spec->multiout.no_share_stream = 1;
1287 codec->no_trigger_sense = 1;
1296 #define AD1983_SPDIF_OUT 0x02
1297 #define AD1983_DAC 0x03
1298 #define AD1983_ADC 0x04
1300 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1301 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1302 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1304 static struct hda_input_mux ad1983_capture_source = {
1310 { "Mix Mono", 0x3 },
1315 * SPDIF playback route
1317 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1319 static char *texts[] = { "PCM", "ADC" };
1321 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1323 uinfo->value.enumerated.items = 2;
1324 if (uinfo->value.enumerated.item > 1)
1325 uinfo->value.enumerated.item = 1;
1326 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1330 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1332 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1333 struct ad198x_spec *spec = codec->spec;
1335 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1339 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1341 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1342 struct ad198x_spec *spec = codec->spec;
1344 if (ucontrol->value.enumerated.item[0] > 1)
1346 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1347 spec->spdif_route = ucontrol->value.enumerated.item[0];
1348 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1349 AC_VERB_SET_CONNECT_SEL,
1356 static struct snd_kcontrol_new ad1983_mixers[] = {
1357 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1358 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1359 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1360 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1361 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1362 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1363 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1364 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1365 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1366 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1367 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1368 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1369 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1370 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1371 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1374 .name = "Capture Source",
1375 .info = ad198x_mux_enum_info,
1376 .get = ad198x_mux_enum_get,
1377 .put = ad198x_mux_enum_put,
1380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1381 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1382 .info = ad1983_spdif_route_info,
1383 .get = ad1983_spdif_route_get,
1384 .put = ad1983_spdif_route_put,
1389 static struct hda_verb ad1983_init_verbs[] = {
1390 /* Front, HP, Mono; mute as default */
1391 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1392 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1393 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1394 /* Beep, PCM, Mic, Line-In: mute */
1395 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1396 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1397 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1398 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1399 /* Front, HP selectors; from Mix */
1400 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1401 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1402 /* Mono selector; from Mix */
1403 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1404 /* Mic selector; Mic */
1405 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1406 /* Line-in selector: Line-in */
1407 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1408 /* Mic boost: 0dB */
1409 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1410 /* Record selector: mic */
1411 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1412 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1413 /* SPDIF route: PCM */
1414 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1416 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1418 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1420 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1422 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1424 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1428 #ifdef CONFIG_SND_HDA_POWER_SAVE
1429 static struct hda_amp_list ad1983_loopbacks[] = {
1430 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1431 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1436 static int patch_ad1983(struct hda_codec *codec)
1438 struct ad198x_spec *spec;
1441 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1447 err = snd_hda_attach_beep_device(codec, 0x10);
1452 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1454 spec->multiout.max_channels = 2;
1455 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1456 spec->multiout.dac_nids = ad1983_dac_nids;
1457 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1458 spec->num_adc_nids = 1;
1459 spec->adc_nids = ad1983_adc_nids;
1460 spec->capsrc_nids = ad1983_capsrc_nids;
1461 spec->input_mux = &ad1983_capture_source;
1462 spec->num_mixers = 1;
1463 spec->mixers[0] = ad1983_mixers;
1464 spec->num_init_verbs = 1;
1465 spec->init_verbs[0] = ad1983_init_verbs;
1466 spec->spdif_route = 0;
1467 #ifdef CONFIG_SND_HDA_POWER_SAVE
1468 spec->loopback.amplist = ad1983_loopbacks;
1470 spec->vmaster_nid = 0x05;
1472 codec->patch_ops = ad198x_patch_ops;
1474 codec->no_trigger_sense = 1;
1481 * AD1981 HD specific
1484 #define AD1981_SPDIF_OUT 0x02
1485 #define AD1981_DAC 0x03
1486 #define AD1981_ADC 0x04
1488 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1489 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1490 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1492 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1493 static struct hda_input_mux ad1981_capture_source = {
1496 { "Front Mic", 0x0 },
1499 { "Mix Mono", 0x3 },
1506 static struct snd_kcontrol_new ad1981_mixers[] = {
1507 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1509 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1512 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1513 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1514 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1515 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1516 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1517 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1518 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1519 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1520 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1521 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1522 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1523 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1524 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1525 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1526 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1527 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1528 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1531 .name = "Capture Source",
1532 .info = ad198x_mux_enum_info,
1533 .get = ad198x_mux_enum_get,
1534 .put = ad198x_mux_enum_put,
1536 /* identical with AD1983 */
1538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1539 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1540 .info = ad1983_spdif_route_info,
1541 .get = ad1983_spdif_route_get,
1542 .put = ad1983_spdif_route_put,
1547 static struct hda_verb ad1981_init_verbs[] = {
1548 /* Front, HP, Mono; mute as default */
1549 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1550 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1551 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1552 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1553 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1554 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1555 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1556 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1557 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1558 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1559 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1560 /* Front, HP selectors; from Mix */
1561 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1562 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1563 /* Mono selector; from Mix */
1564 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1565 /* Mic Mixer; select Front Mic */
1566 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1567 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1568 /* Mic boost: 0dB */
1569 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1570 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1571 /* Record selector: Front mic */
1572 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1573 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1574 /* SPDIF route: PCM */
1575 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1577 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1579 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1581 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1582 /* Front & Rear Mic Pins */
1583 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1584 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1586 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1588 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1589 /* Line-Out as Input: disabled */
1590 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1594 #ifdef CONFIG_SND_HDA_POWER_SAVE
1595 static struct hda_amp_list ad1981_loopbacks[] = {
1596 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1597 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1598 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1599 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1600 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1606 * Patch for HP nx6320
1608 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1609 * speaker output enabled _and_ mute-LED off.
1612 #define AD1981_HP_EVENT 0x37
1613 #define AD1981_MIC_EVENT 0x38
1615 static struct hda_verb ad1981_hp_init_verbs[] = {
1616 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1617 /* pin sensing on HP and Mic jacks */
1618 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1619 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1623 /* turn on/off EAPD (+ mute HP) as a master switch */
1624 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1625 struct snd_ctl_elem_value *ucontrol)
1627 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1628 struct ad198x_spec *spec = codec->spec;
1630 if (! ad198x_eapd_put(kcontrol, ucontrol))
1632 /* change speaker pin appropriately */
1633 snd_hda_codec_write(codec, 0x05, 0,
1634 AC_VERB_SET_PIN_WIDGET_CONTROL,
1635 spec->cur_eapd ? PIN_OUT : 0);
1636 /* toggle HP mute appropriately */
1637 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1639 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1643 /* bind volumes of both NID 0x05 and 0x06 */
1644 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1645 .ops = &snd_hda_bind_vol,
1647 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1648 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1653 /* mute internal speaker if HP is plugged */
1654 static void ad1981_hp_automute(struct hda_codec *codec)
1656 unsigned int present;
1658 present = snd_hda_jack_detect(codec, 0x06);
1659 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1660 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1663 /* toggle input of built-in and mic jack appropriately */
1664 static void ad1981_hp_automic(struct hda_codec *codec)
1666 static struct hda_verb mic_jack_on[] = {
1667 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1668 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1671 static struct hda_verb mic_jack_off[] = {
1672 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1673 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1676 unsigned int present;
1678 present = snd_hda_jack_detect(codec, 0x08);
1680 snd_hda_sequence_write(codec, mic_jack_on);
1682 snd_hda_sequence_write(codec, mic_jack_off);
1685 /* unsolicited event for HP jack sensing */
1686 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1691 case AD1981_HP_EVENT:
1692 ad1981_hp_automute(codec);
1694 case AD1981_MIC_EVENT:
1695 ad1981_hp_automic(codec);
1700 static struct hda_input_mux ad1981_hp_capture_source = {
1704 { "Docking-Station", 0x1 },
1709 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1710 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1713 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1714 .name = "Master Playback Switch",
1715 .info = ad198x_eapd_info,
1716 .get = ad198x_eapd_get,
1717 .put = ad1981_hp_master_sw_put,
1718 .private_value = 0x05,
1720 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1721 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1723 /* FIXME: analog mic/line loopback doesn't work with my tests...
1724 * (although recording is OK)
1726 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1727 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1728 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1729 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1730 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1731 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1732 /* FIXME: does this laptop have analog CD connection? */
1733 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1734 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1736 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1737 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1738 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1739 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1741 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1742 .name = "Capture Source",
1743 .info = ad198x_mux_enum_info,
1744 .get = ad198x_mux_enum_get,
1745 .put = ad198x_mux_enum_put,
1750 /* initialize jack-sensing, too */
1751 static int ad1981_hp_init(struct hda_codec *codec)
1754 ad1981_hp_automute(codec);
1755 ad1981_hp_automic(codec);
1759 /* configuration for Toshiba Laptops */
1760 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1761 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1762 /* pin sensing on HP and Mic jacks */
1763 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1764 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1768 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1769 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1770 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1774 /* configuration for Lenovo Thinkpad T60 */
1775 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1776 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1777 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1778 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1779 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1780 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1781 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1782 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1783 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1784 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1785 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1786 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1789 .name = "Capture Source",
1790 .info = ad198x_mux_enum_info,
1791 .get = ad198x_mux_enum_get,
1792 .put = ad198x_mux_enum_put,
1794 /* identical with AD1983 */
1796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1797 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1798 .info = ad1983_spdif_route_info,
1799 .get = ad1983_spdif_route_get,
1800 .put = ad1983_spdif_route_put,
1805 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1823 static const char *ad1981_models[AD1981_MODELS] = {
1825 [AD1981_THINKPAD] = "thinkpad",
1826 [AD1981_BASIC] = "basic",
1827 [AD1981_TOSHIBA] = "toshiba"
1830 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1831 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1832 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1834 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1835 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1836 /* Lenovo Thinkpad T60/X60/Z6xx */
1837 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1838 /* HP nx6320 (reversed SSID, H/W bug) */
1839 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1843 static int patch_ad1981(struct hda_codec *codec)
1845 struct ad198x_spec *spec;
1846 int err, board_config;
1848 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1854 err = snd_hda_attach_beep_device(codec, 0x10);
1859 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1861 spec->multiout.max_channels = 2;
1862 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1863 spec->multiout.dac_nids = ad1981_dac_nids;
1864 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1865 spec->num_adc_nids = 1;
1866 spec->adc_nids = ad1981_adc_nids;
1867 spec->capsrc_nids = ad1981_capsrc_nids;
1868 spec->input_mux = &ad1981_capture_source;
1869 spec->num_mixers = 1;
1870 spec->mixers[0] = ad1981_mixers;
1871 spec->num_init_verbs = 1;
1872 spec->init_verbs[0] = ad1981_init_verbs;
1873 spec->spdif_route = 0;
1874 #ifdef CONFIG_SND_HDA_POWER_SAVE
1875 spec->loopback.amplist = ad1981_loopbacks;
1877 spec->vmaster_nid = 0x05;
1879 codec->patch_ops = ad198x_patch_ops;
1881 /* override some parameters */
1882 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1885 switch (board_config) {
1887 spec->mixers[0] = ad1981_hp_mixers;
1888 spec->num_init_verbs = 2;
1889 spec->init_verbs[1] = ad1981_hp_init_verbs;
1890 spec->multiout.dig_out_nid = 0;
1891 spec->input_mux = &ad1981_hp_capture_source;
1893 codec->patch_ops.init = ad1981_hp_init;
1894 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1895 /* set the upper-limit for mixer amp to 0dB for avoiding the
1896 * possible damage by overloading
1898 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1899 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1900 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1901 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1902 (1 << AC_AMPCAP_MUTE_SHIFT));
1904 case AD1981_THINKPAD:
1905 spec->mixers[0] = ad1981_thinkpad_mixers;
1906 spec->input_mux = &ad1981_thinkpad_capture_source;
1907 /* set the upper-limit for mixer amp to 0dB for avoiding the
1908 * possible damage by overloading
1910 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1911 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1912 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1913 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1914 (1 << AC_AMPCAP_MUTE_SHIFT));
1916 case AD1981_TOSHIBA:
1917 spec->mixers[0] = ad1981_hp_mixers;
1918 spec->mixers[1] = ad1981_toshiba_mixers;
1919 spec->num_init_verbs = 2;
1920 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1921 spec->multiout.dig_out_nid = 0;
1922 spec->input_mux = &ad1981_hp_capture_source;
1923 codec->patch_ops.init = ad1981_hp_init;
1924 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1928 codec->no_trigger_sense = 1;
1937 * Output pins and routes
1939 * Pin Mix Sel DAC (*)
1940 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1941 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1942 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1943 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1944 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1945 * port-F 0x16 (mute) <- 0x2a <- 06
1946 * port-G 0x24 (mute) <- 0x27 <- 05
1947 * port-H 0x25 (mute) <- 0x28 <- 0a
1948 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1950 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1951 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1953 * Input pins and routes
1955 * pin boost mix input # / adc input #
1956 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1957 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1958 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1959 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1960 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1961 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1962 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1963 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1967 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1968 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1970 * Inputs of Analog Mix (0x20)
1971 * 0:Port-B (front mic)
1972 * 1:Port-C/G/H (line-in)
1974 * 3:Port-D (line-in/2)
1975 * 4:Port-E/G/H (mic-in)
1976 * 5:Port-F (mic2-in)
1982 * 1:Port-B (front mic-in)
1983 * 2:Port-C (line-in)
1984 * 3:Port-F (mic2-in)
1989 * 8:Port-D (line-in/2)
1992 * Proposed pin assignments by the datasheet
1995 * Port-A front headphone
2005 * Port-A front headphone
2007 * C rear line-in/surround
2009 * E rear mic-in/CLFE
2015 * D internal speaker (with EAPD)
2016 * E/F quad mic array
2032 /* reivision id to check workarounds */
2033 #define AD1988A_REV2 0x100200
2035 #define is_rev2(codec) \
2036 ((codec)->vendor_id == 0x11d41988 && \
2037 (codec)->revision_id == AD1988A_REV2)
2043 static hda_nid_t ad1988_6stack_dac_nids[4] = {
2044 0x04, 0x06, 0x05, 0x0a
2047 static hda_nid_t ad1988_3stack_dac_nids[3] = {
2051 /* for AD1988A revision-2, DAC2-4 are swapped */
2052 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2053 0x04, 0x05, 0x0a, 0x06
2056 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2060 static hda_nid_t ad1988_adc_nids[3] = {
2064 static hda_nid_t ad1988_capsrc_nids[3] = {
2068 #define AD1988_SPDIF_OUT 0x02
2069 #define AD1988_SPDIF_OUT_HDMI 0x0b
2070 #define AD1988_SPDIF_IN 0x07
2072 static hda_nid_t ad1989b_slave_dig_outs[] = {
2073 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2076 static struct hda_input_mux ad1988_6stack_capture_source = {
2079 { "Front Mic", 0x1 }, /* port-B */
2080 { "Line", 0x2 }, /* port-C */
2081 { "Mic", 0x4 }, /* port-E */
2087 static struct hda_input_mux ad1988_laptop_capture_source = {
2090 { "Mic/Line", 0x1 }, /* port-B */
2098 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2099 struct snd_ctl_elem_info *uinfo)
2101 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2102 struct ad198x_spec *spec = codec->spec;
2103 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2104 spec->num_channel_mode);
2107 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2108 struct snd_ctl_elem_value *ucontrol)
2110 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2111 struct ad198x_spec *spec = codec->spec;
2112 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2113 spec->num_channel_mode, spec->multiout.max_channels);
2116 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2117 struct snd_ctl_elem_value *ucontrol)
2119 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2120 struct ad198x_spec *spec = codec->spec;
2121 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2122 spec->num_channel_mode,
2123 &spec->multiout.max_channels);
2124 if (err >= 0 && spec->need_dac_fix)
2125 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2130 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2131 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2132 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2133 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2134 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2135 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2139 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2140 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2141 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2142 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2143 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2144 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2148 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2149 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2150 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2151 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2152 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2153 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2154 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2155 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2157 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2158 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2159 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2160 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2161 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2162 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2163 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2164 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2166 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2167 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2169 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2170 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2176 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2177 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2178 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2179 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2180 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2184 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2185 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2186 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2187 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2188 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2192 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2193 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2194 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2195 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2196 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2197 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2198 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2200 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2201 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2202 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2203 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2204 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2205 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2206 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2207 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2209 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2210 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2212 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2213 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2216 .name = "Channel Mode",
2217 .info = ad198x_ch_mode_info,
2218 .get = ad198x_ch_mode_get,
2219 .put = ad198x_ch_mode_put,
2226 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2227 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2228 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2229 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2231 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2232 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2233 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2234 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2235 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2236 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2238 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2239 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2241 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2244 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2245 .name = "External Amplifier",
2246 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2247 .info = ad198x_eapd_info,
2248 .get = ad198x_eapd_get,
2249 .put = ad198x_eapd_put,
2250 .private_value = 0x12, /* port-D */
2257 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2258 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2259 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2260 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2261 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2262 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2263 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2265 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2266 /* The multiple "Capture Source" controls confuse alsamixer
2267 * So call somewhat different..
2269 /* .name = "Capture Source", */
2270 .name = "Input Source",
2272 .info = ad198x_mux_enum_info,
2273 .get = ad198x_mux_enum_get,
2274 .put = ad198x_mux_enum_put,
2279 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2280 struct snd_ctl_elem_info *uinfo)
2282 static char *texts[] = {
2283 "PCM", "ADC1", "ADC2", "ADC3"
2285 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2287 uinfo->value.enumerated.items = 4;
2288 if (uinfo->value.enumerated.item >= 4)
2289 uinfo->value.enumerated.item = 3;
2290 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2294 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2295 struct snd_ctl_elem_value *ucontrol)
2297 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2300 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2303 ucontrol->value.enumerated.item[0] = 0;
2305 sel = snd_hda_codec_read(codec, 0x0b, 0,
2306 AC_VERB_GET_CONNECT_SEL, 0);
2311 ucontrol->value.enumerated.item[0] = sel;
2316 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2317 struct snd_ctl_elem_value *ucontrol)
2319 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2320 unsigned int val, sel;
2323 val = ucontrol->value.enumerated.item[0];
2327 sel = snd_hda_codec_read(codec, 0x1d, 0,
2328 AC_VERB_GET_AMP_GAIN_MUTE,
2330 change = sel & 0x80;
2332 snd_hda_codec_write_cache(codec, 0x1d, 0,
2333 AC_VERB_SET_AMP_GAIN_MUTE,
2335 snd_hda_codec_write_cache(codec, 0x1d, 0,
2336 AC_VERB_SET_AMP_GAIN_MUTE,
2340 sel = snd_hda_codec_read(codec, 0x1d, 0,
2341 AC_VERB_GET_AMP_GAIN_MUTE,
2342 AC_AMP_GET_INPUT | 0x01);
2343 change = sel & 0x80;
2345 snd_hda_codec_write_cache(codec, 0x1d, 0,
2346 AC_VERB_SET_AMP_GAIN_MUTE,
2348 snd_hda_codec_write_cache(codec, 0x1d, 0,
2349 AC_VERB_SET_AMP_GAIN_MUTE,
2352 sel = snd_hda_codec_read(codec, 0x0b, 0,
2353 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2354 change |= sel != val;
2356 snd_hda_codec_write_cache(codec, 0x0b, 0,
2357 AC_VERB_SET_CONNECT_SEL,
2363 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2364 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2366 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2367 .name = "IEC958 Playback Source",
2368 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2369 .info = ad1988_spdif_playback_source_info,
2370 .get = ad1988_spdif_playback_source_get,
2371 .put = ad1988_spdif_playback_source_put,
2376 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2377 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2381 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2382 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2383 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2388 * initialization verbs
2392 * for 6-stack (+dig)
2394 static struct hda_verb ad1988_6stack_init_verbs[] = {
2395 /* Front, Surround, CLFE, side DAC; unmute as default */
2396 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2397 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2398 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2399 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2400 /* Port-A front headphon path */
2401 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2402 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2403 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2404 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2405 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2406 /* Port-D line-out path */
2407 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2408 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2409 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2410 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2411 /* Port-F surround path */
2412 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2413 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2414 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2415 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2416 /* Port-G CLFE path */
2417 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2418 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2419 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2420 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2421 /* Port-H side path */
2422 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2423 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2424 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2425 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2427 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2428 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2429 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2430 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2431 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2432 /* Port-B front mic-in path */
2433 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2434 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2435 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2436 /* Port-C line-in path */
2437 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2438 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2439 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2440 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2441 /* Port-E mic-in path */
2442 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2443 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2444 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2445 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2446 /* Analog CD Input */
2447 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2448 /* Analog Mix output amp */
2449 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2454 static struct hda_verb ad1988_capture_init_verbs[] = {
2455 /* mute analog mix */
2456 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2457 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2458 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2459 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2460 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2461 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2462 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2463 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2464 /* select ADCs - front-mic */
2465 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2466 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2467 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2472 static struct hda_verb ad1988_spdif_init_verbs[] = {
2474 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2475 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2476 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2477 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2479 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2484 static struct hda_verb ad1988_spdif_in_init_verbs[] = {
2485 /* unmute SPDIF input pin */
2486 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2490 /* AD1989 has no ADC -> SPDIF route */
2491 static struct hda_verb ad1989_spdif_init_verbs[] = {
2492 /* SPDIF-1 out pin */
2493 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2494 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2495 /* SPDIF-2/HDMI out pin */
2496 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2497 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2502 * verbs for 3stack (+dig)
2504 static struct hda_verb ad1988_3stack_ch2_init[] = {
2505 /* set port-C to line-in */
2506 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2507 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2508 /* set port-E to mic-in */
2509 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2510 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2514 static struct hda_verb ad1988_3stack_ch6_init[] = {
2515 /* set port-C to surround out */
2516 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2517 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2518 /* set port-E to CLFE out */
2519 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2520 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2524 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2525 { 2, ad1988_3stack_ch2_init },
2526 { 6, ad1988_3stack_ch6_init },
2529 static struct hda_verb ad1988_3stack_init_verbs[] = {
2530 /* Front, Surround, CLFE, side DAC; unmute as default */
2531 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2532 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2533 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2534 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2535 /* Port-A front headphon path */
2536 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2537 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2538 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2539 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2540 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2541 /* Port-D line-out path */
2542 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2543 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2544 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2545 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2547 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2548 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2549 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2550 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2551 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2552 /* Port-B front mic-in path */
2553 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2554 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2555 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2556 /* Port-C line-in/surround path - 6ch mode as default */
2557 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2558 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2559 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2560 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2561 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2562 /* Port-E mic-in/CLFE path - 6ch mode as default */
2563 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2564 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2565 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2566 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2567 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2568 /* mute analog mix */
2569 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2570 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2571 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2572 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2573 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2574 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2575 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2576 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2577 /* select ADCs - front-mic */
2578 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2579 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2580 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2581 /* Analog Mix output amp */
2582 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2587 * verbs for laptop mode (+dig)
2589 static struct hda_verb ad1988_laptop_hp_on[] = {
2590 /* unmute port-A and mute port-D */
2591 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2592 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2595 static struct hda_verb ad1988_laptop_hp_off[] = {
2596 /* mute port-A and unmute port-D */
2597 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2598 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2602 #define AD1988_HP_EVENT 0x01
2604 static struct hda_verb ad1988_laptop_init_verbs[] = {
2605 /* Front, Surround, CLFE, side DAC; unmute as default */
2606 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2607 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2608 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2609 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2610 /* Port-A front headphon path */
2611 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2612 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2613 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2614 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2615 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2616 /* unsolicited event for pin-sense */
2617 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2618 /* Port-D line-out path + EAPD */
2619 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2620 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2621 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2622 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2623 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2625 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2626 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2627 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2628 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2629 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2630 /* Port-B mic-in path */
2631 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2632 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2633 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2634 /* Port-C docking station - try to output */
2635 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2636 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2637 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2638 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2639 /* mute analog mix */
2640 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2641 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2642 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2643 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2644 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2645 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2646 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2647 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2648 /* select ADCs - mic */
2649 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2650 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2651 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2652 /* Analog Mix output amp */
2653 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2657 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2659 if ((res >> 26) != AD1988_HP_EVENT)
2661 if (snd_hda_jack_detect(codec, 0x11))
2662 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2664 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2667 #ifdef CONFIG_SND_HDA_POWER_SAVE
2668 static struct hda_amp_list ad1988_loopbacks[] = {
2669 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2670 { 0x20, HDA_INPUT, 1 }, /* Line */
2671 { 0x20, HDA_INPUT, 4 }, /* Mic */
2672 { 0x20, HDA_INPUT, 6 }, /* CD */
2678 * Automatic parse of I/O pins from the BIOS configuration
2686 static struct snd_kcontrol_new ad1988_control_templates[] = {
2687 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2688 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2689 HDA_BIND_MUTE(NULL, 0, 0, 0),
2692 /* add dynamic controls */
2693 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2696 struct snd_kcontrol_new *knew;
2698 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2699 knew = snd_array_new(&spec->kctls);
2702 *knew = ad1988_control_templates[type];
2703 knew->name = kstrdup(name, GFP_KERNEL);
2706 if (get_amp_nid_(val))
2707 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2708 knew->private_value = val;
2712 #define AD1988_PIN_CD_NID 0x18
2713 #define AD1988_PIN_BEEP_NID 0x10
2715 static hda_nid_t ad1988_mixer_nids[8] = {
2716 /* A B C D E F G H */
2717 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2720 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2722 static hda_nid_t idx_to_dac[8] = {
2723 /* A B C D E F G H */
2724 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2726 static hda_nid_t idx_to_dac_rev2[8] = {
2727 /* A B C D E F G H */
2728 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2731 return idx_to_dac_rev2[idx];
2733 return idx_to_dac[idx];
2736 static hda_nid_t ad1988_boost_nids[8] = {
2737 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2740 static int ad1988_pin_idx(hda_nid_t nid)
2742 static hda_nid_t ad1988_io_pins[8] = {
2743 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2746 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2747 if (ad1988_io_pins[i] == nid)
2749 return 0; /* should be -1 */
2752 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2754 static int loopback_idx[8] = {
2755 2, 0, 1, 3, 4, 5, 1, 4
2758 case AD1988_PIN_CD_NID:
2761 return loopback_idx[ad1988_pin_idx(nid)];
2765 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2767 static int adc_idx[8] = {
2768 0, 1, 2, 8, 4, 3, 6, 7
2771 case AD1988_PIN_CD_NID:
2774 return adc_idx[ad1988_pin_idx(nid)];
2778 /* fill in the dac_nids table from the parsed pin configuration */
2779 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2780 const struct auto_pin_cfg *cfg)
2782 struct ad198x_spec *spec = codec->spec;
2785 spec->multiout.dac_nids = spec->private_dac_nids;
2787 /* check the pins hardwired to audio widget */
2788 for (i = 0; i < cfg->line_outs; i++) {
2789 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2790 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2792 spec->multiout.num_dacs = cfg->line_outs;
2796 /* add playback controls from the parsed DAC table */
2797 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2798 const struct auto_pin_cfg *cfg)
2801 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2805 for (i = 0; i < cfg->line_outs; i++) {
2806 hda_nid_t dac = spec->multiout.dac_nids[i];
2809 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2812 err = add_control(spec, AD_CTL_WIDGET_VOL,
2813 "Center Playback Volume",
2814 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2817 err = add_control(spec, AD_CTL_WIDGET_VOL,
2818 "LFE Playback Volume",
2819 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2822 err = add_control(spec, AD_CTL_BIND_MUTE,
2823 "Center Playback Switch",
2824 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2827 err = add_control(spec, AD_CTL_BIND_MUTE,
2828 "LFE Playback Switch",
2829 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2833 sprintf(name, "%s Playback Volume", chname[i]);
2834 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2835 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2838 sprintf(name, "%s Playback Switch", chname[i]);
2839 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2840 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2848 /* add playback controls for speaker and HP outputs */
2849 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2852 struct ad198x_spec *spec = codec->spec;
2860 idx = ad1988_pin_idx(pin);
2861 nid = ad1988_idx_to_dac(codec, idx);
2862 /* check whether the corresponding DAC was already taken */
2863 for (i = 0; i < spec->autocfg.line_outs; i++) {
2864 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2865 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2869 if (i >= spec->autocfg.line_outs) {
2870 /* specify the DAC as the extra output */
2871 if (!spec->multiout.hp_nid)
2872 spec->multiout.hp_nid = nid;
2874 spec->multiout.extra_out_nid[0] = nid;
2875 /* control HP volume/switch on the output mixer amp */
2876 sprintf(name, "%s Playback Volume", pfx);
2877 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2878 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2882 nid = ad1988_mixer_nids[idx];
2883 sprintf(name, "%s Playback Switch", pfx);
2884 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2885 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2890 /* create input playback/capture controls for the given pin */
2891 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2892 const char *ctlname, int boost)
2897 sprintf(name, "%s Playback Volume", ctlname);
2898 idx = ad1988_pin_to_loopback_idx(pin);
2899 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2900 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2902 sprintf(name, "%s Playback Switch", ctlname);
2903 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2904 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2908 idx = ad1988_pin_idx(pin);
2909 bnid = ad1988_boost_nids[idx];
2911 sprintf(name, "%s Boost", ctlname);
2912 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2913 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2920 /* create playback/capture controls for input pins */
2921 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2922 const struct auto_pin_cfg *cfg)
2924 struct hda_input_mux *imux = &spec->private_imux;
2927 for (i = 0; i < AUTO_PIN_LAST; i++) {
2928 err = new_analog_input(spec, cfg->input_pins[i],
2929 auto_pin_cfg_labels[i],
2930 i <= AUTO_PIN_FRONT_MIC);
2933 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2934 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2937 imux->items[imux->num_items].label = "Mix";
2938 imux->items[imux->num_items].index = 9;
2941 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2942 "Analog Mix Playback Volume",
2943 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2945 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2946 "Analog Mix Playback Switch",
2947 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2953 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2954 hda_nid_t nid, int pin_type,
2958 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2959 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2961 case 0x11: /* port-A - DAC 04 */
2962 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2964 case 0x14: /* port-B - DAC 06 */
2965 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2967 case 0x15: /* port-C - DAC 05 */
2968 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2970 case 0x17: /* port-E - DAC 0a */
2971 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2973 case 0x13: /* mono - DAC 04 */
2974 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2979 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2981 struct ad198x_spec *spec = codec->spec;
2984 for (i = 0; i < spec->autocfg.line_outs; i++) {
2985 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2986 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2990 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2992 struct ad198x_spec *spec = codec->spec;
2995 pin = spec->autocfg.speaker_pins[0];
2996 if (pin) /* connect to front */
2997 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2998 pin = spec->autocfg.hp_pins[0];
2999 if (pin) /* connect to front */
3000 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3003 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3005 struct ad198x_spec *spec = codec->spec;
3008 for (i = 0; i < AUTO_PIN_LAST; i++) {
3009 hda_nid_t nid = spec->autocfg.input_pins[i];
3013 case 0x15: /* port-C */
3014 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3016 case 0x17: /* port-E */
3017 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3020 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3021 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3022 if (nid != AD1988_PIN_CD_NID)
3023 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3025 idx = ad1988_pin_idx(nid);
3026 if (ad1988_boost_nids[idx])
3027 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3028 AC_VERB_SET_AMP_GAIN_MUTE,
3033 /* parse the BIOS configuration and set up the alc_spec */
3034 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3035 static int ad1988_parse_auto_config(struct hda_codec *codec)
3037 struct ad198x_spec *spec = codec->spec;
3040 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3042 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3044 if (! spec->autocfg.line_outs)
3045 return 0; /* can't find valid BIOS pin config */
3046 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3047 (err = ad1988_auto_create_extra_out(codec,
3048 spec->autocfg.speaker_pins[0],
3050 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3051 "Headphone")) < 0 ||
3052 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3055 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3057 if (spec->autocfg.dig_outs)
3058 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3059 if (spec->autocfg.dig_in_pin)
3060 spec->dig_in_nid = AD1988_SPDIF_IN;
3062 if (spec->kctls.list)
3063 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3065 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3067 spec->input_mux = &spec->private_imux;
3072 /* init callback for auto-configuration model -- overriding the default init */
3073 static int ad1988_auto_init(struct hda_codec *codec)
3076 ad1988_auto_init_multi_out(codec);
3077 ad1988_auto_init_extra_out(codec);
3078 ad1988_auto_init_analog_input(codec);
3086 static const char *ad1988_models[AD1988_MODEL_LAST] = {
3087 [AD1988_6STACK] = "6stack",
3088 [AD1988_6STACK_DIG] = "6stack-dig",
3089 [AD1988_3STACK] = "3stack",
3090 [AD1988_3STACK_DIG] = "3stack-dig",
3091 [AD1988_LAPTOP] = "laptop",
3092 [AD1988_LAPTOP_DIG] = "laptop-dig",
3093 [AD1988_AUTO] = "auto",
3096 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
3097 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3098 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3099 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3100 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3104 static int patch_ad1988(struct hda_codec *codec)
3106 struct ad198x_spec *spec;
3107 int err, board_config;
3109 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3116 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3118 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3119 ad1988_models, ad1988_cfg_tbl);
3120 if (board_config < 0) {
3121 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3123 board_config = AD1988_AUTO;
3126 if (board_config == AD1988_AUTO) {
3127 /* automatic parse from the BIOS config */
3128 err = ad1988_parse_auto_config(codec);
3133 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3134 board_config = AD1988_6STACK;
3138 err = snd_hda_attach_beep_device(codec, 0x10);
3143 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3145 switch (board_config) {
3147 case AD1988_6STACK_DIG:
3148 spec->multiout.max_channels = 8;
3149 spec->multiout.num_dacs = 4;
3151 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3153 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3154 spec->input_mux = &ad1988_6stack_capture_source;
3155 spec->num_mixers = 2;
3157 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3159 spec->mixers[0] = ad1988_6stack_mixers1;
3160 spec->mixers[1] = ad1988_6stack_mixers2;
3161 spec->num_init_verbs = 1;
3162 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3163 if (board_config == AD1988_6STACK_DIG) {
3164 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3165 spec->dig_in_nid = AD1988_SPDIF_IN;
3169 case AD1988_3STACK_DIG:
3170 spec->multiout.max_channels = 6;
3171 spec->multiout.num_dacs = 3;
3173 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3175 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3176 spec->input_mux = &ad1988_6stack_capture_source;
3177 spec->channel_mode = ad1988_3stack_modes;
3178 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3179 spec->num_mixers = 2;
3181 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3183 spec->mixers[0] = ad1988_3stack_mixers1;
3184 spec->mixers[1] = ad1988_3stack_mixers2;
3185 spec->num_init_verbs = 1;
3186 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3187 if (board_config == AD1988_3STACK_DIG)
3188 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3191 case AD1988_LAPTOP_DIG:
3192 spec->multiout.max_channels = 2;
3193 spec->multiout.num_dacs = 1;
3194 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3195 spec->input_mux = &ad1988_laptop_capture_source;
3196 spec->num_mixers = 1;
3197 spec->mixers[0] = ad1988_laptop_mixers;
3198 spec->inv_eapd = 1; /* inverted EAPD */
3199 spec->num_init_verbs = 1;
3200 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3201 if (board_config == AD1988_LAPTOP_DIG)
3202 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3206 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3207 spec->adc_nids = ad1988_adc_nids;
3208 spec->capsrc_nids = ad1988_capsrc_nids;
3209 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3210 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3211 if (spec->multiout.dig_out_nid) {
3212 if (codec->vendor_id >= 0x11d4989a) {
3213 spec->mixers[spec->num_mixers++] =
3214 ad1989_spdif_out_mixers;
3215 spec->init_verbs[spec->num_init_verbs++] =
3216 ad1989_spdif_init_verbs;
3217 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3219 spec->mixers[spec->num_mixers++] =
3220 ad1988_spdif_out_mixers;
3221 spec->init_verbs[spec->num_init_verbs++] =
3222 ad1988_spdif_init_verbs;
3225 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3226 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3227 spec->init_verbs[spec->num_init_verbs++] =
3228 ad1988_spdif_in_init_verbs;
3231 codec->patch_ops = ad198x_patch_ops;
3232 switch (board_config) {
3234 codec->patch_ops.init = ad1988_auto_init;
3237 case AD1988_LAPTOP_DIG:
3238 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3241 #ifdef CONFIG_SND_HDA_POWER_SAVE
3242 spec->loopback.amplist = ad1988_loopbacks;
3244 spec->vmaster_nid = 0x04;
3246 codec->no_trigger_sense = 1;
3255 * port-B - front line/mic-in
3256 * port-E - aux in/out
3257 * port-F - aux in/out
3258 * port-C - rear line/mic-in
3259 * port-D - rear line/hp-out
3260 * port-A - front line/hp-out
3262 * AD1984 = AD1884 + two digital mic-ins
3265 * For simplicity, we share the single DAC for both HP and line-outs
3266 * right now. The inidividual playbacks could be easily implemented,
3267 * but no build-up framework is given, so far.
3270 static hda_nid_t ad1884_dac_nids[1] = {
3274 static hda_nid_t ad1884_adc_nids[2] = {
3278 static hda_nid_t ad1884_capsrc_nids[2] = {
3282 #define AD1884_SPDIF_OUT 0x02
3284 static struct hda_input_mux ad1884_capture_source = {
3287 { "Front Mic", 0x0 },
3294 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3295 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3296 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3297 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3298 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3299 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3300 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3301 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3302 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3303 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3304 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3305 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3306 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3307 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3308 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3309 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3310 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3311 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3312 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3314 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3315 /* The multiple "Capture Source" controls confuse alsamixer
3316 * So call somewhat different..
3318 /* .name = "Capture Source", */
3319 .name = "Input Source",
3321 .info = ad198x_mux_enum_info,
3322 .get = ad198x_mux_enum_get,
3323 .put = ad198x_mux_enum_put,
3325 /* SPDIF controls */
3326 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3328 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3329 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3330 /* identical with ad1983 */
3331 .info = ad1983_spdif_route_info,
3332 .get = ad1983_spdif_route_get,
3333 .put = ad1983_spdif_route_put,
3338 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3339 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3340 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3341 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3343 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3349 * initialization verbs
3351 static struct hda_verb ad1884_init_verbs[] = {
3352 /* DACs; mute as default */
3353 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3354 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3355 /* Port-A (HP) mixer */
3356 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3357 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3359 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3360 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3361 /* HP selector - select DAC2 */
3362 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3363 /* Port-D (Line-out) mixer */
3364 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3365 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3367 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3368 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3369 /* Mono-out mixer */
3370 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3371 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3373 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3374 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3376 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3377 /* Port-B (front mic) pin */
3378 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3379 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3380 /* Port-C (rear mic) pin */
3381 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3382 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3383 /* Analog mixer; mute as default */
3384 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3385 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3388 /* Analog Mix output amp */
3389 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3390 /* SPDIF output selector */
3391 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3392 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3396 #ifdef CONFIG_SND_HDA_POWER_SAVE
3397 static struct hda_amp_list ad1884_loopbacks[] = {
3398 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3399 { 0x20, HDA_INPUT, 1 }, /* Mic */
3400 { 0x20, HDA_INPUT, 2 }, /* CD */
3401 { 0x20, HDA_INPUT, 4 }, /* Docking */
3406 static const char *ad1884_slave_vols[] = {
3407 "PCM Playback Volume",
3408 "Mic Playback Volume",
3409 "Mono Playback Volume",
3410 "Front Mic Playback Volume",
3411 "Mic Playback Volume",
3412 "CD Playback Volume",
3413 "Internal Mic Playback Volume",
3414 "Docking Mic Playback Volume",
3415 /* "Beep Playback Volume", */
3416 "IEC958 Playback Volume",
3420 static int patch_ad1884(struct hda_codec *codec)
3422 struct ad198x_spec *spec;
3425 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3431 err = snd_hda_attach_beep_device(codec, 0x10);
3436 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3438 spec->multiout.max_channels = 2;
3439 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3440 spec->multiout.dac_nids = ad1884_dac_nids;
3441 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3442 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3443 spec->adc_nids = ad1884_adc_nids;
3444 spec->capsrc_nids = ad1884_capsrc_nids;
3445 spec->input_mux = &ad1884_capture_source;
3446 spec->num_mixers = 1;
3447 spec->mixers[0] = ad1884_base_mixers;
3448 spec->num_init_verbs = 1;
3449 spec->init_verbs[0] = ad1884_init_verbs;
3450 spec->spdif_route = 0;
3451 #ifdef CONFIG_SND_HDA_POWER_SAVE
3452 spec->loopback.amplist = ad1884_loopbacks;
3454 spec->vmaster_nid = 0x04;
3455 /* we need to cover all playback volumes */
3456 spec->slave_vols = ad1884_slave_vols;
3458 codec->patch_ops = ad198x_patch_ops;
3460 codec->no_trigger_sense = 1;
3466 * Lenovo Thinkpad T61/X61
3468 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3472 { "Internal Mic", 0x1 },
3474 { "Docking-Station", 0x4 },
3480 * Dell Precision T3400
3482 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3485 { "Front Mic", 0x0 },
3492 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3493 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3494 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3495 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3496 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3497 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3498 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3499 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3500 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3501 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3502 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3503 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3504 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3505 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3506 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3507 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3508 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3509 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3510 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3511 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3514 /* The multiple "Capture Source" controls confuse alsamixer
3515 * So call somewhat different..
3517 /* .name = "Capture Source", */
3518 .name = "Input Source",
3520 .info = ad198x_mux_enum_info,
3521 .get = ad198x_mux_enum_get,
3522 .put = ad198x_mux_enum_put,
3524 /* SPDIF controls */
3525 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3527 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3528 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3529 /* identical with ad1983 */
3530 .info = ad1983_spdif_route_info,
3531 .get = ad1983_spdif_route_get,
3532 .put = ad1983_spdif_route_put,
3537 /* additional verbs */
3538 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3539 /* Port-E (docking station mic) pin */
3540 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3541 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3542 /* docking mic boost */
3543 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3544 /* Analog PC Beeper - allow firmware/ACPI beeps */
3545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3546 /* Analog mixer - docking mic; mute as default */
3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3548 /* enable EAPD bit */
3549 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3554 * Dell Precision T3400
3556 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3557 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3558 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3559 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3560 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3561 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3562 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3563 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3564 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3565 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3566 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3567 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3568 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3569 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3570 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3571 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3573 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3574 /* The multiple "Capture Source" controls confuse alsamixer
3575 * So call somewhat different..
3577 /* .name = "Capture Source", */
3578 .name = "Input Source",
3580 .info = ad198x_mux_enum_info,
3581 .get = ad198x_mux_enum_get,
3582 .put = ad198x_mux_enum_put,
3587 /* Digial MIC ADC NID 0x05 + 0x06 */
3588 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3589 struct hda_codec *codec,
3590 unsigned int stream_tag,
3591 unsigned int format,
3592 struct snd_pcm_substream *substream)
3594 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3595 stream_tag, 0, format);
3599 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3600 struct hda_codec *codec,
3601 struct snd_pcm_substream *substream)
3603 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3607 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3613 .prepare = ad1984_pcm_dmic_prepare,
3614 .cleanup = ad1984_pcm_dmic_cleanup
3618 static int ad1984_build_pcms(struct hda_codec *codec)
3620 struct ad198x_spec *spec = codec->spec;
3621 struct hda_pcm *info;
3624 err = ad198x_build_pcms(codec);
3628 info = spec->pcm_rec + codec->num_pcms;
3630 info->name = "AD1984 Digital Mic";
3631 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3639 AD1984_DELL_DESKTOP,
3643 static const char *ad1984_models[AD1984_MODELS] = {
3644 [AD1984_BASIC] = "basic",
3645 [AD1984_THINKPAD] = "thinkpad",
3646 [AD1984_DELL_DESKTOP] = "dell_desktop",
3649 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3650 /* Lenovo Thinkpad T61/X61 */
3651 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3652 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3656 static int patch_ad1984(struct hda_codec *codec)
3658 struct ad198x_spec *spec;
3659 int board_config, err;
3661 err = patch_ad1884(codec);
3665 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3666 ad1984_models, ad1984_cfg_tbl);
3667 switch (board_config) {
3669 /* additional digital mics */
3670 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3671 codec->patch_ops.build_pcms = ad1984_build_pcms;
3673 case AD1984_THINKPAD:
3674 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3675 spec->input_mux = &ad1984_thinkpad_capture_source;
3676 spec->mixers[0] = ad1984_thinkpad_mixers;
3677 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3678 spec->analog_beep = 1;
3680 case AD1984_DELL_DESKTOP:
3681 spec->multiout.dig_out_nid = 0;
3682 spec->input_mux = &ad1984_dell_desktop_capture_source;
3683 spec->mixers[0] = ad1984_dell_desktop_mixers;
3691 * AD1883 / AD1884A / AD1984A / AD1984B
3693 * port-B (0x14) - front mic-in
3694 * port-E (0x1c) - rear mic-in
3695 * port-F (0x16) - CD / ext out
3696 * port-C (0x15) - rear line-in
3697 * port-D (0x12) - rear line-out
3698 * port-A (0x11) - front hp-out
3700 * AD1984A = AD1884A + digital-mic
3701 * AD1883 = equivalent with AD1984A
3702 * AD1984B = AD1984A + extra SPDIF-out
3705 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3708 static hda_nid_t ad1884a_dac_nids[1] = {
3712 #define ad1884a_adc_nids ad1884_adc_nids
3713 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3715 #define AD1884A_SPDIF_OUT 0x02
3717 static struct hda_input_mux ad1884a_capture_source = {
3720 { "Front Mic", 0x0 },
3728 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3729 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3730 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3731 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3732 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3733 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3734 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3735 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3736 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3737 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3738 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3739 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3740 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3741 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3742 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3743 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3744 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3745 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3746 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3747 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3748 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3749 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3750 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3751 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3754 /* The multiple "Capture Source" controls confuse alsamixer
3755 * So call somewhat different..
3757 /* .name = "Capture Source", */
3758 .name = "Input Source",
3760 .info = ad198x_mux_enum_info,
3761 .get = ad198x_mux_enum_get,
3762 .put = ad198x_mux_enum_put,
3764 /* SPDIF controls */
3765 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3767 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3768 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3769 /* identical with ad1983 */
3770 .info = ad1983_spdif_route_info,
3771 .get = ad1983_spdif_route_get,
3772 .put = ad1983_spdif_route_put,
3778 * initialization verbs
3780 static struct hda_verb ad1884a_init_verbs[] = {
3781 /* DACs; unmute as default */
3782 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3783 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3784 /* Port-A (HP) mixer - route only from analog mixer */
3785 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3786 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3788 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3789 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3790 /* Port-D (Line-out) mixer - route only from analog mixer */
3791 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3792 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3794 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3795 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3796 /* Mono-out mixer - route only from analog mixer */
3797 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3798 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3800 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3801 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3802 /* Port-B (front mic) pin */
3803 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3804 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3805 /* Port-C (rear line-in) pin */
3806 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3807 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3808 /* Port-E (rear mic) pin */
3809 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3810 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3811 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3812 /* Port-F (CD) pin */
3813 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3814 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3815 /* Analog mixer; mute as default */
3816 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3817 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3818 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3819 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3820 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3821 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3822 /* Analog Mix output amp */
3823 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3824 /* capture sources */
3825 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3826 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3827 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3828 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3829 /* SPDIF output amp */
3830 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3834 #ifdef CONFIG_SND_HDA_POWER_SAVE
3835 static struct hda_amp_list ad1884a_loopbacks[] = {
3836 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3837 { 0x20, HDA_INPUT, 1 }, /* Mic */
3838 { 0x20, HDA_INPUT, 2 }, /* CD */
3839 { 0x20, HDA_INPUT, 4 }, /* Docking */
3847 * Port A: Headphone jack
3849 * Port C: Internal MIC
3850 * Port D: Dock Line Out (if enabled)
3851 * Port E: Dock Line In (if enabled)
3852 * Port F: Internal speakers
3855 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3856 struct snd_ctl_elem_value *ucontrol)
3858 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3859 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3860 int mute = (!ucontrol->value.integer.value[0] &&
3861 !ucontrol->value.integer.value[1]);
3862 /* toggle GPIO1 according to the mute state */
3863 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3868 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3869 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3871 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3872 .name = "Master Playback Switch",
3873 .subdevice = HDA_SUBDEV_AMP_FLAG,
3874 .info = snd_hda_mixer_amp_switch_info,
3875 .get = snd_hda_mixer_amp_switch_get,
3876 .put = ad1884a_mobile_master_sw_put,
3877 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3879 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3880 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3881 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3882 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3883 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3884 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3885 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3886 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3887 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3888 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3889 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3890 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3891 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3892 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3896 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3897 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3898 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3900 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3901 .name = "Master Playback Switch",
3902 .subdevice = HDA_SUBDEV_AMP_FLAG,
3903 .info = snd_hda_mixer_amp_switch_info,
3904 .get = snd_hda_mixer_amp_switch_get,
3905 .put = ad1884a_mobile_master_sw_put,
3906 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3908 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3909 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3910 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3911 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3912 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3913 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3917 /* mute internal speaker if HP is plugged */
3918 static void ad1884a_hp_automute(struct hda_codec *codec)
3920 unsigned int present;
3922 present = snd_hda_jack_detect(codec, 0x11);
3923 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3924 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3925 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3926 present ? 0x00 : 0x02);
3929 /* switch to external mic if plugged */
3930 static void ad1884a_hp_automic(struct hda_codec *codec)
3932 unsigned int present;
3934 present = snd_hda_jack_detect(codec, 0x14);
3935 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3939 #define AD1884A_HP_EVENT 0x37
3940 #define AD1884A_MIC_EVENT 0x36
3942 /* unsolicited event for HP jack sensing */
3943 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3945 switch (res >> 26) {
3946 case AD1884A_HP_EVENT:
3947 ad1884a_hp_automute(codec);
3949 case AD1884A_MIC_EVENT:
3950 ad1884a_hp_automic(codec);
3955 /* initialize jack-sensing, too */
3956 static int ad1884a_hp_init(struct hda_codec *codec)
3959 ad1884a_hp_automute(codec);
3960 ad1884a_hp_automic(codec);
3964 /* mute internal speaker if HP or docking HP is plugged */
3965 static void ad1884a_laptop_automute(struct hda_codec *codec)
3967 unsigned int present;
3969 present = snd_hda_jack_detect(codec, 0x11);
3971 present = snd_hda_jack_detect(codec, 0x12);
3972 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3973 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3974 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3975 present ? 0x00 : 0x02);
3978 /* switch to external mic if plugged */
3979 static void ad1884a_laptop_automic(struct hda_codec *codec)
3983 if (snd_hda_jack_detect(codec, 0x14))
3985 else if (snd_hda_jack_detect(codec, 0x1c))
3989 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3992 /* unsolicited event for HP jack sensing */
3993 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3996 switch (res >> 26) {
3997 case AD1884A_HP_EVENT:
3998 ad1884a_laptop_automute(codec);
4000 case AD1884A_MIC_EVENT:
4001 ad1884a_laptop_automic(codec);
4006 /* initialize jack-sensing, too */
4007 static int ad1884a_laptop_init(struct hda_codec *codec)
4010 ad1884a_laptop_automute(codec);
4011 ad1884a_laptop_automic(codec);
4015 /* additional verbs for laptop model */
4016 static struct hda_verb ad1884a_laptop_verbs[] = {
4017 /* Port-A (HP) pin - always unmuted */
4018 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4019 /* Port-F (int speaker) mixer - route only from analog mixer */
4020 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4021 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4022 /* Port-F (int speaker) pin */
4023 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4024 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4025 /* required for compaq 6530s/6531s speaker output */
4026 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4027 /* Port-C pin - internal mic-in */
4028 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4029 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4030 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4031 /* Port-D (docking line-out) pin - default unmuted */
4032 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4034 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4035 /* unsolicited event for pin-sense */
4036 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4037 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4038 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4039 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4040 /* allow to touch GPIO1 (for mute control) */
4041 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4042 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4043 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4047 static struct hda_verb ad1884a_mobile_verbs[] = {
4048 /* DACs; unmute as default */
4049 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4050 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4051 /* Port-A (HP) mixer - route only from analog mixer */
4052 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4053 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4055 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4056 /* Port-A (HP) pin - always unmuted */
4057 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4058 /* Port-B (mic jack) pin */
4059 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4060 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4061 /* Port-C (int mic) pin */
4062 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4063 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4064 /* Port-F (int speaker) mixer - route only from analog mixer */
4065 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4066 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4068 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4069 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4070 /* Analog mixer; mute as default */
4071 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4072 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4073 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4074 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4075 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4076 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4077 /* Analog Mix output amp */
4078 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4079 /* capture sources */
4080 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4081 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4082 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4083 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4084 /* unsolicited event for pin-sense */
4085 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4086 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4087 /* allow to touch GPIO1 (for mute control) */
4088 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4089 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4090 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4099 * 0x17 - built-in mic
4102 static struct hda_verb ad1984a_thinkpad_verbs[] = {
4104 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4106 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4108 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4109 /* unsolicited event for pin-sense */
4110 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4111 /* internal mic - dmic */
4112 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4113 /* set magic COEFs for dmic */
4114 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4115 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4119 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4120 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4121 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4122 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4123 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4124 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4125 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4126 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4127 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4128 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4129 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4131 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4132 .name = "Capture Source",
4133 .info = ad198x_mux_enum_info,
4134 .get = ad198x_mux_enum_get,
4135 .put = ad198x_mux_enum_put,
4140 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4144 { "Internal Mic", 0x5 },
4149 /* mute internal speaker if HP is plugged */
4150 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4152 unsigned int present;
4154 present = snd_hda_jack_detect(codec, 0x11);
4155 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4156 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4159 /* unsolicited event for HP jack sensing */
4160 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4163 if ((res >> 26) != AD1884A_HP_EVENT)
4165 ad1984a_thinkpad_automute(codec);
4168 /* initialize jack-sensing, too */
4169 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4172 ad1984a_thinkpad_automute(codec);
4178 * port-A (0x11) - front hp-out
4179 * port-B (0x14) - unused
4180 * port-C (0x15) - unused
4181 * port-D (0x12) - rear line out
4182 * port-E (0x1c) - front mic-in
4183 * port-F (0x16) - Internal speakers
4184 * digital-mic (0x17) - Internal mic
4187 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4188 /* DACs; unmute as default */
4189 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4190 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4191 /* Port-A (HP) mixer - route only from analog mixer */
4192 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4193 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4195 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4196 /* Port-A (HP) pin - always unmuted */
4197 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4198 /* Port-E (int speaker) mixer - route only from analog mixer */
4199 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4201 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4202 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4203 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4204 /* Port-F (int speaker) mixer - route only from analog mixer */
4205 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4206 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4208 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4209 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4210 /* Analog mixer; mute as default */
4211 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4212 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4213 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4214 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4215 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4216 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4217 /* Analog Mix output amp */
4218 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4219 /* capture sources */
4220 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4221 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4222 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4223 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4224 /* unsolicited event for pin-sense */
4225 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4226 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4227 /* allow to touch GPIO1 (for mute control) */
4228 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4229 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4230 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4231 /* internal mic - dmic */
4232 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4233 /* set magic COEFs for dmic */
4234 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4235 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4239 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4240 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4241 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4243 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4244 .subdevice = HDA_SUBDEV_AMP_FLAG,
4245 .name = "Master Playback Switch",
4246 .info = snd_hda_mixer_amp_switch_info,
4247 .get = snd_hda_mixer_amp_switch_get,
4248 .put = ad1884a_mobile_master_sw_put,
4249 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4251 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4252 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4253 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4254 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4255 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4256 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4260 /* switch to external mic if plugged */
4261 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4263 if (snd_hda_jack_detect(codec, 0x1c))
4264 snd_hda_codec_write(codec, 0x0c, 0,
4265 AC_VERB_SET_CONNECT_SEL, 0x4);
4267 snd_hda_codec_write(codec, 0x0c, 0,
4268 AC_VERB_SET_CONNECT_SEL, 0x5);
4272 /* unsolicited event for HP jack sensing */
4273 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4276 switch (res >> 26) {
4277 case AD1884A_HP_EVENT:
4278 ad1884a_hp_automute(codec);
4280 case AD1884A_MIC_EVENT:
4281 ad1984a_touchsmart_automic(codec);
4286 /* initialize jack-sensing, too */
4287 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4290 ad1884a_hp_automute(codec);
4291 ad1984a_touchsmart_automic(codec);
4308 static const char *ad1884a_models[AD1884A_MODELS] = {
4309 [AD1884A_DESKTOP] = "desktop",
4310 [AD1884A_LAPTOP] = "laptop",
4311 [AD1884A_MOBILE] = "mobile",
4312 [AD1884A_THINKPAD] = "thinkpad",
4313 [AD1984A_TOUCHSMART] = "touchsmart",
4316 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4317 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4318 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4319 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4320 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4321 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4322 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4323 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4324 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4325 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4326 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4330 static int patch_ad1884a(struct hda_codec *codec)
4332 struct ad198x_spec *spec;
4333 int err, board_config;
4335 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4341 err = snd_hda_attach_beep_device(codec, 0x10);
4346 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4348 spec->multiout.max_channels = 2;
4349 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4350 spec->multiout.dac_nids = ad1884a_dac_nids;
4351 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4352 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4353 spec->adc_nids = ad1884a_adc_nids;
4354 spec->capsrc_nids = ad1884a_capsrc_nids;
4355 spec->input_mux = &ad1884a_capture_source;
4356 spec->num_mixers = 1;
4357 spec->mixers[0] = ad1884a_base_mixers;
4358 spec->num_init_verbs = 1;
4359 spec->init_verbs[0] = ad1884a_init_verbs;
4360 spec->spdif_route = 0;
4361 #ifdef CONFIG_SND_HDA_POWER_SAVE
4362 spec->loopback.amplist = ad1884a_loopbacks;
4364 codec->patch_ops = ad198x_patch_ops;
4366 /* override some parameters */
4367 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4370 switch (board_config) {
4371 case AD1884A_LAPTOP:
4372 spec->mixers[0] = ad1884a_laptop_mixers;
4373 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4374 spec->multiout.dig_out_nid = 0;
4375 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4376 codec->patch_ops.init = ad1884a_laptop_init;
4377 /* set the upper-limit for mixer amp to 0dB for avoiding the
4378 * possible damage by overloading
4380 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4381 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4382 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4383 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4384 (1 << AC_AMPCAP_MUTE_SHIFT));
4386 case AD1884A_MOBILE:
4387 spec->mixers[0] = ad1884a_mobile_mixers;
4388 spec->init_verbs[0] = ad1884a_mobile_verbs;
4389 spec->multiout.dig_out_nid = 0;
4390 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4391 codec->patch_ops.init = ad1884a_hp_init;
4392 /* set the upper-limit for mixer amp to 0dB for avoiding the
4393 * possible damage by overloading
4395 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4396 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4397 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4398 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4399 (1 << AC_AMPCAP_MUTE_SHIFT));
4401 case AD1884A_THINKPAD:
4402 spec->mixers[0] = ad1984a_thinkpad_mixers;
4403 spec->init_verbs[spec->num_init_verbs++] =
4404 ad1984a_thinkpad_verbs;
4405 spec->multiout.dig_out_nid = 0;
4406 spec->input_mux = &ad1984a_thinkpad_capture_source;
4407 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4408 codec->patch_ops.init = ad1984a_thinkpad_init;
4410 case AD1984A_TOUCHSMART:
4411 spec->mixers[0] = ad1984a_touchsmart_mixers;
4412 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4413 spec->multiout.dig_out_nid = 0;
4414 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4415 codec->patch_ops.init = ad1984a_touchsmart_init;
4416 /* set the upper-limit for mixer amp to 0dB for avoiding the
4417 * possible damage by overloading
4419 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4420 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4421 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4422 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4423 (1 << AC_AMPCAP_MUTE_SHIFT));
4427 codec->no_trigger_sense = 1;
4436 * port-A - front hp-out
4437 * port-B - front mic-in
4438 * port-C - rear line-in, shared surr-out (3stack)
4439 * port-D - rear line-out
4440 * port-E - rear mic-in, shared clfe-out (3stack)
4441 * port-F - rear surr-out (6stack)
4442 * port-G - rear clfe-out (6stack)
4445 static hda_nid_t ad1882_dac_nids[3] = {
4449 static hda_nid_t ad1882_adc_nids[2] = {
4453 static hda_nid_t ad1882_capsrc_nids[2] = {
4457 #define AD1882_SPDIF_OUT 0x02
4459 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4460 static struct hda_input_mux ad1882_capture_source = {
4463 { "Front Mic", 0x1 },
4471 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4472 static struct hda_input_mux ad1882a_capture_source = {
4475 { "Front Mic", 0x1 },
4478 { "Digital Mic", 0x06 },
4483 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4484 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4485 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4486 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4487 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4488 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4489 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4490 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4491 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4493 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4494 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4495 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4496 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4497 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4498 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4499 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4502 /* The multiple "Capture Source" controls confuse alsamixer
4503 * So call somewhat different..
4505 /* .name = "Capture Source", */
4506 .name = "Input Source",
4508 .info = ad198x_mux_enum_info,
4509 .get = ad198x_mux_enum_get,
4510 .put = ad198x_mux_enum_put,
4512 /* SPDIF controls */
4513 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4516 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4517 /* identical with ad1983 */
4518 .info = ad1983_spdif_route_info,
4519 .get = ad1983_spdif_route_get,
4520 .put = ad1983_spdif_route_put,
4525 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4526 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4527 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4528 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4529 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4530 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4531 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4532 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4533 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4537 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4538 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4539 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4540 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4541 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4542 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4543 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4544 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4545 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4546 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4550 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4551 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4552 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4553 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4556 .name = "Channel Mode",
4557 .info = ad198x_ch_mode_info,
4558 .get = ad198x_ch_mode_get,
4559 .put = ad198x_ch_mode_put,
4564 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4565 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4566 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4567 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4571 static struct hda_verb ad1882_ch2_init[] = {
4572 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4573 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4574 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4575 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4576 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4577 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4581 static struct hda_verb ad1882_ch4_init[] = {
4582 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4583 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4584 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4585 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4586 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4587 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4591 static struct hda_verb ad1882_ch6_init[] = {
4592 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4593 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4594 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4595 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4596 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4597 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4601 static struct hda_channel_mode ad1882_modes[3] = {
4602 { 2, ad1882_ch2_init },
4603 { 4, ad1882_ch4_init },
4604 { 6, ad1882_ch6_init },
4608 * initialization verbs
4610 static struct hda_verb ad1882_init_verbs[] = {
4611 /* DACs; mute as default */
4612 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4613 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4614 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4615 /* Port-A (HP) mixer */
4616 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4617 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4619 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4620 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4621 /* HP selector - select DAC2 */
4622 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4623 /* Port-D (Line-out) mixer */
4624 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4625 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4627 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4628 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4629 /* Mono-out mixer */
4630 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4631 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4633 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4634 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4635 /* Port-B (front mic) pin */
4636 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4637 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4638 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4639 /* Port-C (line-in) pin */
4640 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4641 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4642 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4643 /* Port-C mixer - mute as input */
4644 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4645 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4646 /* Port-E (mic-in) pin */
4647 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4648 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4649 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4650 /* Port-E mixer - mute as input */
4651 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4652 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4653 /* Port-F (surround) */
4654 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4655 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4657 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4658 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4659 /* Analog mixer; mute as default */
4660 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4661 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4662 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4663 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4664 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4665 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4666 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4667 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4668 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4669 /* Analog Mix output amp */
4670 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4671 /* SPDIF output selector */
4672 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4673 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4674 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4678 #ifdef CONFIG_SND_HDA_POWER_SAVE
4679 static struct hda_amp_list ad1882_loopbacks[] = {
4680 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4681 { 0x20, HDA_INPUT, 1 }, /* Mic */
4682 { 0x20, HDA_INPUT, 4 }, /* Line */
4683 { 0x20, HDA_INPUT, 6 }, /* CD */
4695 static const char *ad1882_models[AD1986A_MODELS] = {
4696 [AD1882_3STACK] = "3stack",
4697 [AD1882_6STACK] = "6stack",
4701 static int patch_ad1882(struct hda_codec *codec)
4703 struct ad198x_spec *spec;
4704 int err, board_config;
4706 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4712 err = snd_hda_attach_beep_device(codec, 0x10);
4717 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4719 spec->multiout.max_channels = 6;
4720 spec->multiout.num_dacs = 3;
4721 spec->multiout.dac_nids = ad1882_dac_nids;
4722 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4723 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4724 spec->adc_nids = ad1882_adc_nids;
4725 spec->capsrc_nids = ad1882_capsrc_nids;
4726 if (codec->vendor_id == 0x11d41882)
4727 spec->input_mux = &ad1882_capture_source;
4729 spec->input_mux = &ad1882a_capture_source;
4730 spec->num_mixers = 2;
4731 spec->mixers[0] = ad1882_base_mixers;
4732 if (codec->vendor_id == 0x11d41882)
4733 spec->mixers[1] = ad1882_loopback_mixers;
4735 spec->mixers[1] = ad1882a_loopback_mixers;
4736 spec->num_init_verbs = 1;
4737 spec->init_verbs[0] = ad1882_init_verbs;
4738 spec->spdif_route = 0;
4739 #ifdef CONFIG_SND_HDA_POWER_SAVE
4740 spec->loopback.amplist = ad1882_loopbacks;
4742 spec->vmaster_nid = 0x04;
4744 codec->patch_ops = ad198x_patch_ops;
4746 /* override some parameters */
4747 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4748 ad1882_models, NULL);
4749 switch (board_config) {
4752 spec->num_mixers = 3;
4753 spec->mixers[2] = ad1882_3stack_mixers;
4754 spec->channel_mode = ad1882_modes;
4755 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4756 spec->need_dac_fix = 1;
4757 spec->multiout.max_channels = 2;
4758 spec->multiout.num_dacs = 1;
4761 spec->num_mixers = 3;
4762 spec->mixers[2] = ad1882_6stack_mixers;
4766 codec->no_trigger_sense = 1;
4775 static struct hda_codec_preset snd_hda_preset_analog[] = {
4776 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4777 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4778 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4779 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4780 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4781 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4782 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4783 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4784 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4785 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4786 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4787 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4788 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4789 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4790 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4794 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4796 MODULE_LICENSE("GPL");
4797 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4799 static struct hda_codec_preset_list analog_list = {
4800 .preset = snd_hda_preset_analog,
4801 .owner = THIS_MODULE,
4804 static int __init patch_analog_init(void)
4806 return snd_hda_add_codec_preset(&analog_list);
4809 static void __exit patch_analog_exit(void)
4811 snd_hda_delete_codec_preset(&analog_list);
4814 module_init(patch_analog_init)
4815 module_exit(patch_analog_exit)