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);
532 static struct hda_codec_ops ad198x_patch_ops = {
533 .build_controls = ad198x_build_controls,
534 .build_pcms = ad198x_build_pcms,
537 #ifdef CONFIG_SND_HDA_POWER_SAVE
538 .check_power_status = ad198x_check_power_status,
540 #ifdef SND_HDA_NEEDS_RESUME
541 .suspend = ad198x_suspend,
543 .reboot_notify = ad198x_shutup,
549 * the private value = nid
551 #define ad198x_eapd_info snd_ctl_boolean_mono_info
553 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_value *ucontrol)
556 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
557 struct ad198x_spec *spec = codec->spec;
559 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
561 ucontrol->value.integer.value[0] = spec->cur_eapd;
565 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
566 struct snd_ctl_elem_value *ucontrol)
568 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
569 struct ad198x_spec *spec = codec->spec;
570 hda_nid_t nid = kcontrol->private_value & 0xff;
572 eapd = !!ucontrol->value.integer.value[0];
575 if (eapd == spec->cur_eapd)
577 spec->cur_eapd = eapd;
578 snd_hda_codec_write_cache(codec, nid,
579 0, AC_VERB_SET_EAPD_BTLENABLE,
584 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
585 struct snd_ctl_elem_info *uinfo);
586 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
587 struct snd_ctl_elem_value *ucontrol);
588 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
589 struct snd_ctl_elem_value *ucontrol);
596 #define AD1986A_SPDIF_OUT 0x02
597 #define AD1986A_FRONT_DAC 0x03
598 #define AD1986A_SURR_DAC 0x04
599 #define AD1986A_CLFE_DAC 0x05
600 #define AD1986A_ADC 0x06
602 static hda_nid_t ad1986a_dac_nids[3] = {
603 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
605 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
606 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
608 static struct hda_input_mux ad1986a_capture_source = {
622 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
623 .ops = &snd_hda_bind_vol,
625 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
626 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
627 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
632 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
633 .ops = &snd_hda_bind_sw,
635 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
636 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
637 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
645 static struct snd_kcontrol_new ad1986a_mixers[] = {
647 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
649 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
650 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
651 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
652 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
653 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
654 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
655 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
656 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
657 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
658 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
659 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
660 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
661 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
662 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
663 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
664 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
665 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
666 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
667 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
668 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
669 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
670 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
671 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
672 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
673 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
675 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
676 .name = "Capture Source",
677 .info = ad198x_mux_enum_info,
678 .get = ad198x_mux_enum_get,
679 .put = ad198x_mux_enum_put,
681 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
685 /* additional mixers for 3stack mode */
686 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
688 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
689 .name = "Channel Mode",
690 .info = ad198x_ch_mode_info,
691 .get = ad198x_ch_mode_get,
692 .put = ad198x_ch_mode_put,
697 /* laptop model - 2ch only */
698 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
700 /* master controls both pins 0x1a and 0x1b */
701 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
702 .ops = &snd_hda_bind_vol,
704 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
705 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
710 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
711 .ops = &snd_hda_bind_sw,
713 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
714 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
719 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
720 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
721 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
722 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
723 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
724 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
725 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
726 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
727 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
728 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
729 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
730 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
731 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
732 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
734 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
735 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
736 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
737 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
739 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
740 .name = "Capture Source",
741 .info = ad198x_mux_enum_info,
742 .get = ad198x_mux_enum_get,
743 .put = ad198x_mux_enum_put,
748 /* laptop-eapd model - 2ch only */
750 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
754 { "Internal Mic", 0x4 },
759 static struct hda_input_mux ad1986a_automic_capture_source = {
767 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
768 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
769 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
773 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
774 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
775 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
776 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
777 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
778 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
779 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
780 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
782 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
783 .name = "Capture Source",
784 .info = ad198x_mux_enum_info,
785 .get = ad198x_mux_enum_get,
786 .put = ad198x_mux_enum_put,
789 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
790 .name = "External Amplifier",
791 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
792 .info = ad198x_eapd_info,
793 .get = ad198x_eapd_get,
794 .put = ad198x_eapd_put,
795 .private_value = 0x1b, /* port-D */
800 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
801 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
802 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
806 /* re-connect the mic boost input according to the jack sensing */
807 static void ad1986a_automic(struct hda_codec *codec)
809 unsigned int present;
810 present = snd_hda_jack_detect(codec, 0x1f);
811 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
812 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
816 #define AD1986A_MIC_EVENT 0x36
818 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
821 if ((res >> 26) != AD1986A_MIC_EVENT)
823 ad1986a_automic(codec);
826 static int ad1986a_automic_init(struct hda_codec *codec)
829 ad1986a_automic(codec);
833 /* laptop-automute - 2ch only */
835 static void ad1986a_update_hp(struct hda_codec *codec)
837 struct ad198x_spec *spec = codec->spec;
840 if (spec->jack_present)
841 mute = HDA_AMP_MUTE; /* mute internal speaker */
843 /* unmute internal speaker if necessary */
844 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
845 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
849 static void ad1986a_hp_automute(struct hda_codec *codec)
851 struct ad198x_spec *spec = codec->spec;
853 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
854 if (spec->inv_jack_detect)
855 spec->jack_present = !spec->jack_present;
856 ad1986a_update_hp(codec);
859 #define AD1986A_HP_EVENT 0x37
861 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
863 if ((res >> 26) != AD1986A_HP_EVENT)
865 ad1986a_hp_automute(codec);
868 static int ad1986a_hp_init(struct hda_codec *codec)
871 ad1986a_hp_automute(codec);
875 /* bind hp and internal speaker mute (with plug check) */
876 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
877 struct snd_ctl_elem_value *ucontrol)
879 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
880 long *valp = ucontrol->value.integer.value;
883 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
885 valp[0] ? 0 : HDA_AMP_MUTE);
886 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
888 valp[1] ? 0 : HDA_AMP_MUTE);
890 ad1986a_update_hp(codec);
894 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
895 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
897 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
898 .name = "Master Playback Switch",
899 .subdevice = HDA_SUBDEV_AMP_FLAG,
900 .info = snd_hda_mixer_amp_switch_info,
901 .get = snd_hda_mixer_amp_switch_get,
902 .put = ad1986a_hp_master_sw_put,
903 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
910 * initialization verbs
912 static struct hda_verb ad1986a_init_verbs[] = {
913 /* Front, Surround, CLFE DAC; mute as default */
914 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
915 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
916 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
918 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
919 /* HP, Line-Out, Surround, CLFE selectors */
920 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
921 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
922 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
923 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
925 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
926 /* Mic selector: Mic 1/2 pin */
927 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
928 /* Line-in selector: Line-in */
929 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
931 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
932 /* Record selector: mic */
933 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
934 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
935 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
936 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
937 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
938 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
939 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
941 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
942 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
943 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
944 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
945 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
946 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
947 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
949 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
950 /* Front, Surround, CLFE Pins */
951 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
952 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
953 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
955 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
957 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
958 /* Line, Aux, CD, Beep-In Pin */
959 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
960 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
961 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
962 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
963 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
967 static struct hda_verb ad1986a_ch2_init[] = {
968 /* Surround out -> Line In */
969 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
970 /* Line-in selectors */
971 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
973 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
974 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
975 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
979 static struct hda_verb ad1986a_ch4_init[] = {
980 /* Surround out -> Surround */
981 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
982 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
984 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
985 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
989 static struct hda_verb ad1986a_ch6_init[] = {
990 /* Surround out -> Surround out */
991 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
992 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
994 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
995 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
999 static struct hda_channel_mode ad1986a_modes[3] = {
1000 { 2, ad1986a_ch2_init },
1001 { 4, ad1986a_ch4_init },
1002 { 6, ad1986a_ch6_init },
1005 /* eapd initialization */
1006 static struct hda_verb ad1986a_eapd_init_verbs[] = {
1007 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1011 static struct hda_verb ad1986a_automic_verbs[] = {
1012 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1013 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1014 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1015 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1016 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1020 /* Ultra initialization */
1021 static struct hda_verb ad1986a_ultra_init[] = {
1022 /* eapd initialization */
1023 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1024 /* CLFE -> Mic in */
1025 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1026 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1027 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1031 /* pin sensing on HP jack */
1032 static struct hda_verb ad1986a_hp_init_verbs[] = {
1033 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1037 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1040 switch (res >> 26) {
1041 case AD1986A_HP_EVENT:
1042 ad1986a_hp_automute(codec);
1044 case AD1986A_MIC_EVENT:
1045 ad1986a_automic(codec);
1050 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1053 ad1986a_hp_automute(codec);
1054 ad1986a_automic(codec);
1064 AD1986A_LAPTOP_EAPD,
1065 AD1986A_LAPTOP_AUTOMUTE,
1068 AD1986A_SAMSUNG_P50,
1072 static const char *ad1986a_models[AD1986A_MODELS] = {
1073 [AD1986A_6STACK] = "6stack",
1074 [AD1986A_3STACK] = "3stack",
1075 [AD1986A_LAPTOP] = "laptop",
1076 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1077 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1078 [AD1986A_ULTRA] = "ultra",
1079 [AD1986A_SAMSUNG] = "samsung",
1080 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1083 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1084 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1085 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1086 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1087 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1088 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1089 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1090 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1091 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1092 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1093 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1094 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1095 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1096 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1097 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1098 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1099 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1100 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1101 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1102 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1103 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1104 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1105 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1106 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1107 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1108 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1109 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1110 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1114 #ifdef CONFIG_SND_HDA_POWER_SAVE
1115 static struct hda_amp_list ad1986a_loopbacks[] = {
1116 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1117 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1118 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1119 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1120 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1125 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1127 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1128 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1131 static int patch_ad1986a(struct hda_codec *codec)
1133 struct ad198x_spec *spec;
1134 int err, board_config;
1136 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1142 err = snd_hda_attach_beep_device(codec, 0x19);
1147 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1149 spec->multiout.max_channels = 6;
1150 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1151 spec->multiout.dac_nids = ad1986a_dac_nids;
1152 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1153 spec->num_adc_nids = 1;
1154 spec->adc_nids = ad1986a_adc_nids;
1155 spec->capsrc_nids = ad1986a_capsrc_nids;
1156 spec->input_mux = &ad1986a_capture_source;
1157 spec->num_mixers = 1;
1158 spec->mixers[0] = ad1986a_mixers;
1159 spec->num_init_verbs = 1;
1160 spec->init_verbs[0] = ad1986a_init_verbs;
1161 #ifdef CONFIG_SND_HDA_POWER_SAVE
1162 spec->loopback.amplist = ad1986a_loopbacks;
1164 spec->vmaster_nid = 0x1b;
1165 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1167 codec->patch_ops = ad198x_patch_ops;
1169 /* override some parameters */
1170 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1173 switch (board_config) {
1174 case AD1986A_3STACK:
1175 spec->num_mixers = 2;
1176 spec->mixers[1] = ad1986a_3st_mixers;
1177 spec->num_init_verbs = 2;
1178 spec->init_verbs[1] = ad1986a_ch2_init;
1179 spec->channel_mode = ad1986a_modes;
1180 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1181 spec->need_dac_fix = 1;
1182 spec->multiout.max_channels = 2;
1183 spec->multiout.num_dacs = 1;
1185 case AD1986A_LAPTOP:
1186 spec->mixers[0] = ad1986a_laptop_mixers;
1187 spec->multiout.max_channels = 2;
1188 spec->multiout.num_dacs = 1;
1189 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1191 case AD1986A_LAPTOP_EAPD:
1192 spec->num_mixers = 3;
1193 spec->mixers[0] = ad1986a_laptop_master_mixers;
1194 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1195 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1196 spec->num_init_verbs = 2;
1197 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1198 spec->multiout.max_channels = 2;
1199 spec->multiout.num_dacs = 1;
1200 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1201 if (!is_jack_available(codec, 0x25))
1202 spec->multiout.dig_out_nid = 0;
1203 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1205 case AD1986A_SAMSUNG:
1206 spec->num_mixers = 2;
1207 spec->mixers[0] = ad1986a_laptop_master_mixers;
1208 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1209 spec->num_init_verbs = 3;
1210 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1211 spec->init_verbs[2] = ad1986a_automic_verbs;
1212 spec->multiout.max_channels = 2;
1213 spec->multiout.num_dacs = 1;
1214 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1215 if (!is_jack_available(codec, 0x25))
1216 spec->multiout.dig_out_nid = 0;
1217 spec->input_mux = &ad1986a_automic_capture_source;
1218 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1219 codec->patch_ops.init = ad1986a_automic_init;
1221 case AD1986A_SAMSUNG_P50:
1222 spec->num_mixers = 2;
1223 spec->mixers[0] = ad1986a_automute_master_mixers;
1224 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1225 spec->num_init_verbs = 4;
1226 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1227 spec->init_verbs[2] = ad1986a_automic_verbs;
1228 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1229 spec->multiout.max_channels = 2;
1230 spec->multiout.num_dacs = 1;
1231 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1232 if (!is_jack_available(codec, 0x25))
1233 spec->multiout.dig_out_nid = 0;
1234 spec->input_mux = &ad1986a_automic_capture_source;
1235 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1236 codec->patch_ops.init = ad1986a_samsung_p50_init;
1238 case AD1986A_LAPTOP_AUTOMUTE:
1239 spec->num_mixers = 3;
1240 spec->mixers[0] = ad1986a_automute_master_mixers;
1241 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1242 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1243 spec->num_init_verbs = 3;
1244 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1245 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1246 spec->multiout.max_channels = 2;
1247 spec->multiout.num_dacs = 1;
1248 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1249 if (!is_jack_available(codec, 0x25))
1250 spec->multiout.dig_out_nid = 0;
1251 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1252 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1253 codec->patch_ops.init = ad1986a_hp_init;
1254 /* Lenovo N100 seems to report the reversed bit
1255 * for HP jack-sensing
1257 spec->inv_jack_detect = 1;
1260 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1261 spec->num_init_verbs = 2;
1262 spec->init_verbs[1] = ad1986a_ultra_init;
1263 spec->multiout.max_channels = 2;
1264 spec->multiout.num_dacs = 1;
1265 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1266 spec->multiout.dig_out_nid = 0;
1270 /* AD1986A has a hardware problem that it can't share a stream
1271 * with multiple output pins. The copy of front to surrounds
1272 * causes noisy or silent outputs at a certain timing, e.g.
1273 * changing the volume.
1274 * So, let's disable the shared stream.
1276 spec->multiout.no_share_stream = 1;
1278 codec->no_trigger_sense = 1;
1287 #define AD1983_SPDIF_OUT 0x02
1288 #define AD1983_DAC 0x03
1289 #define AD1983_ADC 0x04
1291 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1292 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1293 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1295 static struct hda_input_mux ad1983_capture_source = {
1301 { "Mix Mono", 0x3 },
1306 * SPDIF playback route
1308 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1310 static char *texts[] = { "PCM", "ADC" };
1312 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1314 uinfo->value.enumerated.items = 2;
1315 if (uinfo->value.enumerated.item > 1)
1316 uinfo->value.enumerated.item = 1;
1317 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1321 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1324 struct ad198x_spec *spec = codec->spec;
1326 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1330 static int ad1983_spdif_route_put(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 if (ucontrol->value.enumerated.item[0] > 1)
1337 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1338 spec->spdif_route = ucontrol->value.enumerated.item[0];
1339 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1340 AC_VERB_SET_CONNECT_SEL,
1347 static struct snd_kcontrol_new ad1983_mixers[] = {
1348 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1349 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1350 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1351 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1352 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1353 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1354 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1355 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1356 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1357 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1358 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1359 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1360 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1361 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1362 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1364 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1365 .name = "Capture Source",
1366 .info = ad198x_mux_enum_info,
1367 .get = ad198x_mux_enum_get,
1368 .put = ad198x_mux_enum_put,
1371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1372 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1373 .info = ad1983_spdif_route_info,
1374 .get = ad1983_spdif_route_get,
1375 .put = ad1983_spdif_route_put,
1380 static struct hda_verb ad1983_init_verbs[] = {
1381 /* Front, HP, Mono; mute as default */
1382 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1383 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1384 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1385 /* Beep, PCM, Mic, Line-In: mute */
1386 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1387 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1388 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1389 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1390 /* Front, HP selectors; from Mix */
1391 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1392 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1393 /* Mono selector; from Mix */
1394 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1395 /* Mic selector; Mic */
1396 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1397 /* Line-in selector: Line-in */
1398 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1399 /* Mic boost: 0dB */
1400 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1401 /* Record selector: mic */
1402 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1403 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1404 /* SPDIF route: PCM */
1405 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1407 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1409 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1411 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1413 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1415 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1419 #ifdef CONFIG_SND_HDA_POWER_SAVE
1420 static struct hda_amp_list ad1983_loopbacks[] = {
1421 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1422 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1427 static int patch_ad1983(struct hda_codec *codec)
1429 struct ad198x_spec *spec;
1432 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1438 err = snd_hda_attach_beep_device(codec, 0x10);
1443 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1445 spec->multiout.max_channels = 2;
1446 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1447 spec->multiout.dac_nids = ad1983_dac_nids;
1448 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1449 spec->num_adc_nids = 1;
1450 spec->adc_nids = ad1983_adc_nids;
1451 spec->capsrc_nids = ad1983_capsrc_nids;
1452 spec->input_mux = &ad1983_capture_source;
1453 spec->num_mixers = 1;
1454 spec->mixers[0] = ad1983_mixers;
1455 spec->num_init_verbs = 1;
1456 spec->init_verbs[0] = ad1983_init_verbs;
1457 spec->spdif_route = 0;
1458 #ifdef CONFIG_SND_HDA_POWER_SAVE
1459 spec->loopback.amplist = ad1983_loopbacks;
1461 spec->vmaster_nid = 0x05;
1463 codec->patch_ops = ad198x_patch_ops;
1465 codec->no_trigger_sense = 1;
1472 * AD1981 HD specific
1475 #define AD1981_SPDIF_OUT 0x02
1476 #define AD1981_DAC 0x03
1477 #define AD1981_ADC 0x04
1479 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1480 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1481 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1483 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1484 static struct hda_input_mux ad1981_capture_source = {
1487 { "Front Mic", 0x0 },
1490 { "Mix Mono", 0x3 },
1497 static struct snd_kcontrol_new ad1981_mixers[] = {
1498 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1499 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1500 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1507 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1509 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1512 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1513 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1514 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1515 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1516 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1517 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1518 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1519 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 .name = "Capture Source",
1523 .info = ad198x_mux_enum_info,
1524 .get = ad198x_mux_enum_get,
1525 .put = ad198x_mux_enum_put,
1527 /* identical with AD1983 */
1529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1530 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1531 .info = ad1983_spdif_route_info,
1532 .get = ad1983_spdif_route_get,
1533 .put = ad1983_spdif_route_put,
1538 static struct hda_verb ad1981_init_verbs[] = {
1539 /* Front, HP, Mono; mute as default */
1540 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1541 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1542 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1543 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1544 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1545 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1546 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1547 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1548 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1549 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1550 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1551 /* Front, HP selectors; from Mix */
1552 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1553 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1554 /* Mono selector; from Mix */
1555 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1556 /* Mic Mixer; select Front Mic */
1557 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1558 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1559 /* Mic boost: 0dB */
1560 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1561 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1562 /* Record selector: Front mic */
1563 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1564 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1565 /* SPDIF route: PCM */
1566 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1568 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1570 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1572 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1573 /* Front & Rear Mic Pins */
1574 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1575 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1577 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1579 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1580 /* Line-Out as Input: disabled */
1581 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1585 #ifdef CONFIG_SND_HDA_POWER_SAVE
1586 static struct hda_amp_list ad1981_loopbacks[] = {
1587 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1588 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1589 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1590 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1591 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1597 * Patch for HP nx6320
1599 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1600 * speaker output enabled _and_ mute-LED off.
1603 #define AD1981_HP_EVENT 0x37
1604 #define AD1981_MIC_EVENT 0x38
1606 static struct hda_verb ad1981_hp_init_verbs[] = {
1607 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1608 /* pin sensing on HP and Mic jacks */
1609 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1610 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1614 /* turn on/off EAPD (+ mute HP) as a master switch */
1615 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1616 struct snd_ctl_elem_value *ucontrol)
1618 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1619 struct ad198x_spec *spec = codec->spec;
1621 if (! ad198x_eapd_put(kcontrol, ucontrol))
1623 /* change speaker pin appropriately */
1624 snd_hda_codec_write(codec, 0x05, 0,
1625 AC_VERB_SET_PIN_WIDGET_CONTROL,
1626 spec->cur_eapd ? PIN_OUT : 0);
1627 /* toggle HP mute appropriately */
1628 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1630 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1634 /* bind volumes of both NID 0x05 and 0x06 */
1635 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1636 .ops = &snd_hda_bind_vol,
1638 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1639 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1644 /* mute internal speaker if HP is plugged */
1645 static void ad1981_hp_automute(struct hda_codec *codec)
1647 unsigned int present;
1649 present = snd_hda_jack_detect(codec, 0x06);
1650 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1651 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1654 /* toggle input of built-in and mic jack appropriately */
1655 static void ad1981_hp_automic(struct hda_codec *codec)
1657 static struct hda_verb mic_jack_on[] = {
1658 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1659 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1662 static struct hda_verb mic_jack_off[] = {
1663 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1664 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1667 unsigned int present;
1669 present = snd_hda_jack_detect(codec, 0x08);
1671 snd_hda_sequence_write(codec, mic_jack_on);
1673 snd_hda_sequence_write(codec, mic_jack_off);
1676 /* unsolicited event for HP jack sensing */
1677 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1682 case AD1981_HP_EVENT:
1683 ad1981_hp_automute(codec);
1685 case AD1981_MIC_EVENT:
1686 ad1981_hp_automic(codec);
1691 static struct hda_input_mux ad1981_hp_capture_source = {
1695 { "Docking-Station", 0x1 },
1700 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1701 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1703 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1704 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1705 .name = "Master Playback Switch",
1706 .info = ad198x_eapd_info,
1707 .get = ad198x_eapd_get,
1708 .put = ad1981_hp_master_sw_put,
1709 .private_value = 0x05,
1711 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1712 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1714 /* FIXME: analog mic/line loopback doesn't work with my tests...
1715 * (although recording is OK)
1717 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1718 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1719 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1720 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1721 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1722 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1723 /* FIXME: does this laptop have analog CD connection? */
1724 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1725 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1727 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1728 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1729 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1730 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1732 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1733 .name = "Capture Source",
1734 .info = ad198x_mux_enum_info,
1735 .get = ad198x_mux_enum_get,
1736 .put = ad198x_mux_enum_put,
1741 /* initialize jack-sensing, too */
1742 static int ad1981_hp_init(struct hda_codec *codec)
1745 ad1981_hp_automute(codec);
1746 ad1981_hp_automic(codec);
1750 /* configuration for Toshiba Laptops */
1751 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1752 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1753 /* pin sensing on HP and Mic jacks */
1754 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1755 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1759 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1760 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1761 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1765 /* configuration for Lenovo Thinkpad T60 */
1766 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1767 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1768 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1769 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1770 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1771 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1772 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1773 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1774 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1775 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1776 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1777 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780 .name = "Capture Source",
1781 .info = ad198x_mux_enum_info,
1782 .get = ad198x_mux_enum_get,
1783 .put = ad198x_mux_enum_put,
1785 /* identical with AD1983 */
1787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1788 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1789 .info = ad1983_spdif_route_info,
1790 .get = ad1983_spdif_route_get,
1791 .put = ad1983_spdif_route_put,
1796 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1814 static const char *ad1981_models[AD1981_MODELS] = {
1816 [AD1981_THINKPAD] = "thinkpad",
1817 [AD1981_BASIC] = "basic",
1818 [AD1981_TOSHIBA] = "toshiba"
1821 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1822 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1823 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1825 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1826 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1827 /* Lenovo Thinkpad T60/X60/Z6xx */
1828 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1829 /* HP nx6320 (reversed SSID, H/W bug) */
1830 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1834 static int patch_ad1981(struct hda_codec *codec)
1836 struct ad198x_spec *spec;
1837 int err, board_config;
1839 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1845 err = snd_hda_attach_beep_device(codec, 0x10);
1850 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1852 spec->multiout.max_channels = 2;
1853 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1854 spec->multiout.dac_nids = ad1981_dac_nids;
1855 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1856 spec->num_adc_nids = 1;
1857 spec->adc_nids = ad1981_adc_nids;
1858 spec->capsrc_nids = ad1981_capsrc_nids;
1859 spec->input_mux = &ad1981_capture_source;
1860 spec->num_mixers = 1;
1861 spec->mixers[0] = ad1981_mixers;
1862 spec->num_init_verbs = 1;
1863 spec->init_verbs[0] = ad1981_init_verbs;
1864 spec->spdif_route = 0;
1865 #ifdef CONFIG_SND_HDA_POWER_SAVE
1866 spec->loopback.amplist = ad1981_loopbacks;
1868 spec->vmaster_nid = 0x05;
1870 codec->patch_ops = ad198x_patch_ops;
1872 /* override some parameters */
1873 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1876 switch (board_config) {
1878 spec->mixers[0] = ad1981_hp_mixers;
1879 spec->num_init_verbs = 2;
1880 spec->init_verbs[1] = ad1981_hp_init_verbs;
1881 spec->multiout.dig_out_nid = 0;
1882 spec->input_mux = &ad1981_hp_capture_source;
1884 codec->patch_ops.init = ad1981_hp_init;
1885 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1886 /* set the upper-limit for mixer amp to 0dB for avoiding the
1887 * possible damage by overloading
1889 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1890 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1891 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1892 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1893 (1 << AC_AMPCAP_MUTE_SHIFT));
1895 case AD1981_THINKPAD:
1896 spec->mixers[0] = ad1981_thinkpad_mixers;
1897 spec->input_mux = &ad1981_thinkpad_capture_source;
1898 /* set the upper-limit for mixer amp to 0dB for avoiding the
1899 * possible damage by overloading
1901 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1902 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1903 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1904 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1905 (1 << AC_AMPCAP_MUTE_SHIFT));
1907 case AD1981_TOSHIBA:
1908 spec->mixers[0] = ad1981_hp_mixers;
1909 spec->mixers[1] = ad1981_toshiba_mixers;
1910 spec->num_init_verbs = 2;
1911 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1912 spec->multiout.dig_out_nid = 0;
1913 spec->input_mux = &ad1981_hp_capture_source;
1914 codec->patch_ops.init = ad1981_hp_init;
1915 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1919 codec->no_trigger_sense = 1;
1928 * Output pins and routes
1930 * Pin Mix Sel DAC (*)
1931 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1932 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1933 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1934 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1935 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1936 * port-F 0x16 (mute) <- 0x2a <- 06
1937 * port-G 0x24 (mute) <- 0x27 <- 05
1938 * port-H 0x25 (mute) <- 0x28 <- 0a
1939 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1941 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1942 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1944 * Input pins and routes
1946 * pin boost mix input # / adc input #
1947 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1948 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1949 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1950 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1951 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1952 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1953 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1954 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1958 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1959 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1961 * Inputs of Analog Mix (0x20)
1962 * 0:Port-B (front mic)
1963 * 1:Port-C/G/H (line-in)
1965 * 3:Port-D (line-in/2)
1966 * 4:Port-E/G/H (mic-in)
1967 * 5:Port-F (mic2-in)
1973 * 1:Port-B (front mic-in)
1974 * 2:Port-C (line-in)
1975 * 3:Port-F (mic2-in)
1980 * 8:Port-D (line-in/2)
1983 * Proposed pin assignments by the datasheet
1986 * Port-A front headphone
1996 * Port-A front headphone
1998 * C rear line-in/surround
2000 * E rear mic-in/CLFE
2006 * D internal speaker (with EAPD)
2007 * E/F quad mic array
2023 /* reivision id to check workarounds */
2024 #define AD1988A_REV2 0x100200
2026 #define is_rev2(codec) \
2027 ((codec)->vendor_id == 0x11d41988 && \
2028 (codec)->revision_id == AD1988A_REV2)
2034 static hda_nid_t ad1988_6stack_dac_nids[4] = {
2035 0x04, 0x06, 0x05, 0x0a
2038 static hda_nid_t ad1988_3stack_dac_nids[3] = {
2042 /* for AD1988A revision-2, DAC2-4 are swapped */
2043 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2044 0x04, 0x05, 0x0a, 0x06
2047 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2051 static hda_nid_t ad1988_adc_nids[3] = {
2055 static hda_nid_t ad1988_capsrc_nids[3] = {
2059 #define AD1988_SPDIF_OUT 0x02
2060 #define AD1988_SPDIF_OUT_HDMI 0x0b
2061 #define AD1988_SPDIF_IN 0x07
2063 static hda_nid_t ad1989b_slave_dig_outs[] = {
2064 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2067 static struct hda_input_mux ad1988_6stack_capture_source = {
2070 { "Front Mic", 0x1 }, /* port-B */
2071 { "Line", 0x2 }, /* port-C */
2072 { "Mic", 0x4 }, /* port-E */
2078 static struct hda_input_mux ad1988_laptop_capture_source = {
2081 { "Mic/Line", 0x1 }, /* port-B */
2089 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2090 struct snd_ctl_elem_info *uinfo)
2092 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2093 struct ad198x_spec *spec = codec->spec;
2094 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2095 spec->num_channel_mode);
2098 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2099 struct snd_ctl_elem_value *ucontrol)
2101 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2102 struct ad198x_spec *spec = codec->spec;
2103 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2104 spec->num_channel_mode, spec->multiout.max_channels);
2107 static int ad198x_ch_mode_put(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 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2113 spec->num_channel_mode,
2114 &spec->multiout.max_channels);
2115 if (err >= 0 && spec->need_dac_fix)
2116 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2121 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2122 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2123 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2124 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2125 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2126 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2130 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2131 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2132 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2133 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2134 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2135 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2139 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2140 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2141 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2142 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2143 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2144 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2145 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2146 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2148 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2149 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2150 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2151 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2152 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2153 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2154 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2155 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2157 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2158 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2160 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2161 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2167 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2168 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2169 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2170 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2171 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2175 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2176 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2177 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2178 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2179 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2183 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2184 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2185 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2186 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2187 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2188 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2189 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2191 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2192 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2193 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2194 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2195 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2196 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2197 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2198 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2200 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2201 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2203 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2204 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2206 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2207 .name = "Channel Mode",
2208 .info = ad198x_ch_mode_info,
2209 .get = ad198x_ch_mode_get,
2210 .put = ad198x_ch_mode_put,
2217 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2218 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2219 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2220 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2222 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2223 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2224 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2225 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2226 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2227 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2229 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2230 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2232 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2235 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2236 .name = "External Amplifier",
2237 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2238 .info = ad198x_eapd_info,
2239 .get = ad198x_eapd_get,
2240 .put = ad198x_eapd_put,
2241 .private_value = 0x12, /* port-D */
2248 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2249 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2250 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2251 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2252 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2253 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2254 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2256 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2257 /* The multiple "Capture Source" controls confuse alsamixer
2258 * So call somewhat different..
2260 /* .name = "Capture Source", */
2261 .name = "Input Source",
2263 .info = ad198x_mux_enum_info,
2264 .get = ad198x_mux_enum_get,
2265 .put = ad198x_mux_enum_put,
2270 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2271 struct snd_ctl_elem_info *uinfo)
2273 static char *texts[] = {
2274 "PCM", "ADC1", "ADC2", "ADC3"
2276 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2278 uinfo->value.enumerated.items = 4;
2279 if (uinfo->value.enumerated.item >= 4)
2280 uinfo->value.enumerated.item = 3;
2281 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2285 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2286 struct snd_ctl_elem_value *ucontrol)
2288 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2291 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2294 ucontrol->value.enumerated.item[0] = 0;
2296 sel = snd_hda_codec_read(codec, 0x0b, 0,
2297 AC_VERB_GET_CONNECT_SEL, 0);
2302 ucontrol->value.enumerated.item[0] = sel;
2307 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2308 struct snd_ctl_elem_value *ucontrol)
2310 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2311 unsigned int val, sel;
2314 val = ucontrol->value.enumerated.item[0];
2318 sel = snd_hda_codec_read(codec, 0x1d, 0,
2319 AC_VERB_GET_AMP_GAIN_MUTE,
2321 change = sel & 0x80;
2323 snd_hda_codec_write_cache(codec, 0x1d, 0,
2324 AC_VERB_SET_AMP_GAIN_MUTE,
2326 snd_hda_codec_write_cache(codec, 0x1d, 0,
2327 AC_VERB_SET_AMP_GAIN_MUTE,
2331 sel = snd_hda_codec_read(codec, 0x1d, 0,
2332 AC_VERB_GET_AMP_GAIN_MUTE,
2333 AC_AMP_GET_INPUT | 0x01);
2334 change = sel & 0x80;
2336 snd_hda_codec_write_cache(codec, 0x1d, 0,
2337 AC_VERB_SET_AMP_GAIN_MUTE,
2339 snd_hda_codec_write_cache(codec, 0x1d, 0,
2340 AC_VERB_SET_AMP_GAIN_MUTE,
2343 sel = snd_hda_codec_read(codec, 0x0b, 0,
2344 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2345 change |= sel != val;
2347 snd_hda_codec_write_cache(codec, 0x0b, 0,
2348 AC_VERB_SET_CONNECT_SEL,
2354 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2355 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2358 .name = "IEC958 Playback Source",
2359 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2360 .info = ad1988_spdif_playback_source_info,
2361 .get = ad1988_spdif_playback_source_get,
2362 .put = ad1988_spdif_playback_source_put,
2367 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2368 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2372 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2373 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2374 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2379 * initialization verbs
2383 * for 6-stack (+dig)
2385 static struct hda_verb ad1988_6stack_init_verbs[] = {
2386 /* Front, Surround, CLFE, side DAC; unmute as default */
2387 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2388 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2389 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2390 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2391 /* Port-A front headphon path */
2392 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2393 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2394 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2395 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2396 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2397 /* Port-D line-out path */
2398 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2399 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2400 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2401 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2402 /* Port-F surround path */
2403 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2404 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2405 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2406 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2407 /* Port-G CLFE path */
2408 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2409 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2410 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2411 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2412 /* Port-H side path */
2413 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2414 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2415 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2416 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2418 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2419 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2420 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2421 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2422 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2423 /* Port-B front mic-in path */
2424 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2425 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2426 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2427 /* Port-C line-in path */
2428 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2429 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2430 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2431 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2432 /* Port-E mic-in path */
2433 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2434 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2435 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2436 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2437 /* Analog CD Input */
2438 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2439 /* Analog Mix output amp */
2440 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2445 static struct hda_verb ad1988_capture_init_verbs[] = {
2446 /* mute analog mix */
2447 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2448 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2449 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2450 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2451 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2452 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2453 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2454 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2455 /* select ADCs - front-mic */
2456 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2457 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2458 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2463 static struct hda_verb ad1988_spdif_init_verbs[] = {
2465 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2466 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2467 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2468 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2470 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2475 static struct hda_verb ad1988_spdif_in_init_verbs[] = {
2476 /* unmute SPDIF input pin */
2477 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2481 /* AD1989 has no ADC -> SPDIF route */
2482 static struct hda_verb ad1989_spdif_init_verbs[] = {
2483 /* SPDIF-1 out pin */
2484 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2485 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2486 /* SPDIF-2/HDMI out pin */
2487 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2488 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2493 * verbs for 3stack (+dig)
2495 static struct hda_verb ad1988_3stack_ch2_init[] = {
2496 /* set port-C to line-in */
2497 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2498 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2499 /* set port-E to mic-in */
2500 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2501 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2505 static struct hda_verb ad1988_3stack_ch6_init[] = {
2506 /* set port-C to surround out */
2507 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2508 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2509 /* set port-E to CLFE out */
2510 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2511 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2515 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2516 { 2, ad1988_3stack_ch2_init },
2517 { 6, ad1988_3stack_ch6_init },
2520 static struct hda_verb ad1988_3stack_init_verbs[] = {
2521 /* Front, Surround, CLFE, side DAC; unmute as default */
2522 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2523 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2524 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2525 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2526 /* Port-A front headphon path */
2527 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2528 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2529 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2530 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2531 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2532 /* Port-D line-out path */
2533 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2534 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2535 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2536 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2538 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2539 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2540 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2541 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2542 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2543 /* Port-B front mic-in path */
2544 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2545 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2546 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2547 /* Port-C line-in/surround path - 6ch mode as default */
2548 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2549 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2550 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2551 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2552 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2553 /* Port-E mic-in/CLFE path - 6ch mode as default */
2554 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2555 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2556 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2557 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2558 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2559 /* mute analog mix */
2560 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2561 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2562 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2563 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2564 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2565 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2566 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2567 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2568 /* select ADCs - front-mic */
2569 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2570 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2571 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2572 /* Analog Mix output amp */
2573 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2578 * verbs for laptop mode (+dig)
2580 static struct hda_verb ad1988_laptop_hp_on[] = {
2581 /* unmute port-A and mute port-D */
2582 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2583 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2586 static struct hda_verb ad1988_laptop_hp_off[] = {
2587 /* mute port-A and unmute port-D */
2588 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2589 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2593 #define AD1988_HP_EVENT 0x01
2595 static struct hda_verb ad1988_laptop_init_verbs[] = {
2596 /* Front, Surround, CLFE, side DAC; unmute as default */
2597 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2598 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2599 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2600 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2601 /* Port-A front headphon path */
2602 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2603 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2604 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2605 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2606 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2607 /* unsolicited event for pin-sense */
2608 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2609 /* Port-D line-out path + EAPD */
2610 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2611 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2612 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2613 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2614 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2616 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2617 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2618 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2619 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2620 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2621 /* Port-B mic-in path */
2622 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2623 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2624 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2625 /* Port-C docking station - try to output */
2626 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2627 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2628 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2629 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2630 /* mute analog mix */
2631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2635 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2636 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2637 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2638 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2639 /* select ADCs - mic */
2640 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2641 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2642 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2643 /* Analog Mix output amp */
2644 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2648 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2650 if ((res >> 26) != AD1988_HP_EVENT)
2652 if (snd_hda_jack_detect(codec, 0x11))
2653 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2655 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2658 #ifdef CONFIG_SND_HDA_POWER_SAVE
2659 static struct hda_amp_list ad1988_loopbacks[] = {
2660 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2661 { 0x20, HDA_INPUT, 1 }, /* Line */
2662 { 0x20, HDA_INPUT, 4 }, /* Mic */
2663 { 0x20, HDA_INPUT, 6 }, /* CD */
2669 * Automatic parse of I/O pins from the BIOS configuration
2677 static struct snd_kcontrol_new ad1988_control_templates[] = {
2678 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2679 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2680 HDA_BIND_MUTE(NULL, 0, 0, 0),
2683 /* add dynamic controls */
2684 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2687 struct snd_kcontrol_new *knew;
2689 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2690 knew = snd_array_new(&spec->kctls);
2693 *knew = ad1988_control_templates[type];
2694 knew->name = kstrdup(name, GFP_KERNEL);
2697 if (get_amp_nid_(val))
2698 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2699 knew->private_value = val;
2703 #define AD1988_PIN_CD_NID 0x18
2704 #define AD1988_PIN_BEEP_NID 0x10
2706 static hda_nid_t ad1988_mixer_nids[8] = {
2707 /* A B C D E F G H */
2708 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2711 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2713 static hda_nid_t idx_to_dac[8] = {
2714 /* A B C D E F G H */
2715 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2717 static hda_nid_t idx_to_dac_rev2[8] = {
2718 /* A B C D E F G H */
2719 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2722 return idx_to_dac_rev2[idx];
2724 return idx_to_dac[idx];
2727 static hda_nid_t ad1988_boost_nids[8] = {
2728 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2731 static int ad1988_pin_idx(hda_nid_t nid)
2733 static hda_nid_t ad1988_io_pins[8] = {
2734 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2737 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2738 if (ad1988_io_pins[i] == nid)
2740 return 0; /* should be -1 */
2743 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2745 static int loopback_idx[8] = {
2746 2, 0, 1, 3, 4, 5, 1, 4
2749 case AD1988_PIN_CD_NID:
2752 return loopback_idx[ad1988_pin_idx(nid)];
2756 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2758 static int adc_idx[8] = {
2759 0, 1, 2, 8, 4, 3, 6, 7
2762 case AD1988_PIN_CD_NID:
2765 return adc_idx[ad1988_pin_idx(nid)];
2769 /* fill in the dac_nids table from the parsed pin configuration */
2770 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2771 const struct auto_pin_cfg *cfg)
2773 struct ad198x_spec *spec = codec->spec;
2776 spec->multiout.dac_nids = spec->private_dac_nids;
2778 /* check the pins hardwired to audio widget */
2779 for (i = 0; i < cfg->line_outs; i++) {
2780 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2781 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2783 spec->multiout.num_dacs = cfg->line_outs;
2787 /* add playback controls from the parsed DAC table */
2788 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2789 const struct auto_pin_cfg *cfg)
2792 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2796 for (i = 0; i < cfg->line_outs; i++) {
2797 hda_nid_t dac = spec->multiout.dac_nids[i];
2800 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2803 err = add_control(spec, AD_CTL_WIDGET_VOL,
2804 "Center Playback Volume",
2805 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2808 err = add_control(spec, AD_CTL_WIDGET_VOL,
2809 "LFE Playback Volume",
2810 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2813 err = add_control(spec, AD_CTL_BIND_MUTE,
2814 "Center Playback Switch",
2815 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2818 err = add_control(spec, AD_CTL_BIND_MUTE,
2819 "LFE Playback Switch",
2820 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2824 sprintf(name, "%s Playback Volume", chname[i]);
2825 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2826 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2829 sprintf(name, "%s Playback Switch", chname[i]);
2830 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2831 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2839 /* add playback controls for speaker and HP outputs */
2840 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2843 struct ad198x_spec *spec = codec->spec;
2851 idx = ad1988_pin_idx(pin);
2852 nid = ad1988_idx_to_dac(codec, idx);
2853 /* check whether the corresponding DAC was already taken */
2854 for (i = 0; i < spec->autocfg.line_outs; i++) {
2855 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2856 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2860 if (i >= spec->autocfg.line_outs) {
2861 /* specify the DAC as the extra output */
2862 if (!spec->multiout.hp_nid)
2863 spec->multiout.hp_nid = nid;
2865 spec->multiout.extra_out_nid[0] = nid;
2866 /* control HP volume/switch on the output mixer amp */
2867 sprintf(name, "%s Playback Volume", pfx);
2868 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2869 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2873 nid = ad1988_mixer_nids[idx];
2874 sprintf(name, "%s Playback Switch", pfx);
2875 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2876 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2881 /* create input playback/capture controls for the given pin */
2882 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2883 const char *ctlname, int ctlidx, int boost)
2888 sprintf(name, "%s Playback Volume", ctlname);
2889 idx = ad1988_pin_to_loopback_idx(pin);
2890 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2891 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2893 sprintf(name, "%s Playback Switch", ctlname);
2894 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2895 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2899 idx = ad1988_pin_idx(pin);
2900 bnid = ad1988_boost_nids[idx];
2902 sprintf(name, "%s Boost", ctlname);
2903 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2904 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2911 /* create playback/capture controls for input pins */
2912 static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
2913 const struct auto_pin_cfg *cfg)
2915 struct ad198x_spec *spec = codec->spec;
2916 struct hda_input_mux *imux = &spec->private_imux;
2917 int i, err, type, type_idx;
2919 for (i = 0; i < cfg->num_inputs; i++) {
2921 type = cfg->inputs[i].type;
2922 label = hda_get_autocfg_input_label(codec, cfg, i);
2923 snd_hda_add_imux_item(imux, label,
2924 ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
2926 err = new_analog_input(spec, cfg->inputs[i].pin,
2928 type == AUTO_PIN_MIC);
2932 snd_hda_add_imux_item(imux, "Mix", 9, NULL);
2934 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2935 "Analog Mix Playback Volume",
2936 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2938 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2939 "Analog Mix Playback Switch",
2940 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2946 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2947 hda_nid_t nid, int pin_type,
2951 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2952 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2954 case 0x11: /* port-A - DAC 04 */
2955 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2957 case 0x14: /* port-B - DAC 06 */
2958 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2960 case 0x15: /* port-C - DAC 05 */
2961 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2963 case 0x17: /* port-E - DAC 0a */
2964 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2966 case 0x13: /* mono - DAC 04 */
2967 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2972 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2974 struct ad198x_spec *spec = codec->spec;
2977 for (i = 0; i < spec->autocfg.line_outs; i++) {
2978 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2979 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2983 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2985 struct ad198x_spec *spec = codec->spec;
2988 pin = spec->autocfg.speaker_pins[0];
2989 if (pin) /* connect to front */
2990 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2991 pin = spec->autocfg.hp_pins[0];
2992 if (pin) /* connect to front */
2993 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2996 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2998 struct ad198x_spec *spec = codec->spec;
2999 const struct auto_pin_cfg *cfg = &spec->autocfg;
3002 for (i = 0; i < cfg->num_inputs; i++) {
3003 hda_nid_t nid = cfg->inputs[i].pin;
3005 case 0x15: /* port-C */
3006 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3008 case 0x17: /* port-E */
3009 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3012 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3013 i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
3014 if (nid != AD1988_PIN_CD_NID)
3015 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3017 idx = ad1988_pin_idx(nid);
3018 if (ad1988_boost_nids[idx])
3019 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3020 AC_VERB_SET_AMP_GAIN_MUTE,
3025 /* parse the BIOS configuration and set up the alc_spec */
3026 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3027 static int ad1988_parse_auto_config(struct hda_codec *codec)
3029 struct ad198x_spec *spec = codec->spec;
3032 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3034 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3036 if (! spec->autocfg.line_outs)
3037 return 0; /* can't find valid BIOS pin config */
3038 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3039 (err = ad1988_auto_create_extra_out(codec,
3040 spec->autocfg.speaker_pins[0],
3042 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3043 "Headphone")) < 0 ||
3044 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3047 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3049 if (spec->autocfg.dig_outs)
3050 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3051 if (spec->autocfg.dig_in_pin)
3052 spec->dig_in_nid = AD1988_SPDIF_IN;
3054 if (spec->kctls.list)
3055 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3057 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3059 spec->input_mux = &spec->private_imux;
3064 /* init callback for auto-configuration model -- overriding the default init */
3065 static int ad1988_auto_init(struct hda_codec *codec)
3068 ad1988_auto_init_multi_out(codec);
3069 ad1988_auto_init_extra_out(codec);
3070 ad1988_auto_init_analog_input(codec);
3078 static const char *ad1988_models[AD1988_MODEL_LAST] = {
3079 [AD1988_6STACK] = "6stack",
3080 [AD1988_6STACK_DIG] = "6stack-dig",
3081 [AD1988_3STACK] = "3stack",
3082 [AD1988_3STACK_DIG] = "3stack-dig",
3083 [AD1988_LAPTOP] = "laptop",
3084 [AD1988_LAPTOP_DIG] = "laptop-dig",
3085 [AD1988_AUTO] = "auto",
3088 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
3089 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3090 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3091 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3092 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3096 static int patch_ad1988(struct hda_codec *codec)
3098 struct ad198x_spec *spec;
3099 int err, board_config;
3101 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3108 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3110 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3111 ad1988_models, ad1988_cfg_tbl);
3112 if (board_config < 0) {
3113 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3115 board_config = AD1988_AUTO;
3118 if (board_config == AD1988_AUTO) {
3119 /* automatic parse from the BIOS config */
3120 err = ad1988_parse_auto_config(codec);
3125 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3126 board_config = AD1988_6STACK;
3130 err = snd_hda_attach_beep_device(codec, 0x10);
3135 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3137 switch (board_config) {
3139 case AD1988_6STACK_DIG:
3140 spec->multiout.max_channels = 8;
3141 spec->multiout.num_dacs = 4;
3143 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3145 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3146 spec->input_mux = &ad1988_6stack_capture_source;
3147 spec->num_mixers = 2;
3149 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3151 spec->mixers[0] = ad1988_6stack_mixers1;
3152 spec->mixers[1] = ad1988_6stack_mixers2;
3153 spec->num_init_verbs = 1;
3154 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3155 if (board_config == AD1988_6STACK_DIG) {
3156 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3157 spec->dig_in_nid = AD1988_SPDIF_IN;
3161 case AD1988_3STACK_DIG:
3162 spec->multiout.max_channels = 6;
3163 spec->multiout.num_dacs = 3;
3165 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3167 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3168 spec->input_mux = &ad1988_6stack_capture_source;
3169 spec->channel_mode = ad1988_3stack_modes;
3170 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3171 spec->num_mixers = 2;
3173 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3175 spec->mixers[0] = ad1988_3stack_mixers1;
3176 spec->mixers[1] = ad1988_3stack_mixers2;
3177 spec->num_init_verbs = 1;
3178 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3179 if (board_config == AD1988_3STACK_DIG)
3180 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3183 case AD1988_LAPTOP_DIG:
3184 spec->multiout.max_channels = 2;
3185 spec->multiout.num_dacs = 1;
3186 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3187 spec->input_mux = &ad1988_laptop_capture_source;
3188 spec->num_mixers = 1;
3189 spec->mixers[0] = ad1988_laptop_mixers;
3190 spec->inv_eapd = 1; /* inverted EAPD */
3191 spec->num_init_verbs = 1;
3192 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3193 if (board_config == AD1988_LAPTOP_DIG)
3194 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3198 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3199 spec->adc_nids = ad1988_adc_nids;
3200 spec->capsrc_nids = ad1988_capsrc_nids;
3201 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3202 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3203 if (spec->multiout.dig_out_nid) {
3204 if (codec->vendor_id >= 0x11d4989a) {
3205 spec->mixers[spec->num_mixers++] =
3206 ad1989_spdif_out_mixers;
3207 spec->init_verbs[spec->num_init_verbs++] =
3208 ad1989_spdif_init_verbs;
3209 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3211 spec->mixers[spec->num_mixers++] =
3212 ad1988_spdif_out_mixers;
3213 spec->init_verbs[spec->num_init_verbs++] =
3214 ad1988_spdif_init_verbs;
3217 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3218 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3219 spec->init_verbs[spec->num_init_verbs++] =
3220 ad1988_spdif_in_init_verbs;
3223 codec->patch_ops = ad198x_patch_ops;
3224 switch (board_config) {
3226 codec->patch_ops.init = ad1988_auto_init;
3229 case AD1988_LAPTOP_DIG:
3230 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3233 #ifdef CONFIG_SND_HDA_POWER_SAVE
3234 spec->loopback.amplist = ad1988_loopbacks;
3236 spec->vmaster_nid = 0x04;
3238 codec->no_trigger_sense = 1;
3247 * port-B - front line/mic-in
3248 * port-E - aux in/out
3249 * port-F - aux in/out
3250 * port-C - rear line/mic-in
3251 * port-D - rear line/hp-out
3252 * port-A - front line/hp-out
3254 * AD1984 = AD1884 + two digital mic-ins
3257 * For simplicity, we share the single DAC for both HP and line-outs
3258 * right now. The inidividual playbacks could be easily implemented,
3259 * but no build-up framework is given, so far.
3262 static hda_nid_t ad1884_dac_nids[1] = {
3266 static hda_nid_t ad1884_adc_nids[2] = {
3270 static hda_nid_t ad1884_capsrc_nids[2] = {
3274 #define AD1884_SPDIF_OUT 0x02
3276 static struct hda_input_mux ad1884_capture_source = {
3279 { "Front Mic", 0x0 },
3286 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3287 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3288 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3289 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3290 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3291 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3292 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3293 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3294 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3295 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3296 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3297 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3298 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3299 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3300 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3301 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3302 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3303 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3304 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3306 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3307 /* The multiple "Capture Source" controls confuse alsamixer
3308 * So call somewhat different..
3310 /* .name = "Capture Source", */
3311 .name = "Input Source",
3313 .info = ad198x_mux_enum_info,
3314 .get = ad198x_mux_enum_get,
3315 .put = ad198x_mux_enum_put,
3317 /* SPDIF controls */
3318 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3320 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3321 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3322 /* identical with ad1983 */
3323 .info = ad1983_spdif_route_info,
3324 .get = ad1983_spdif_route_get,
3325 .put = ad1983_spdif_route_put,
3330 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3331 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3332 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3333 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3335 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3341 * initialization verbs
3343 static struct hda_verb ad1884_init_verbs[] = {
3344 /* DACs; mute as default */
3345 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3346 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3347 /* Port-A (HP) mixer */
3348 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3349 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3351 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3352 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3353 /* HP selector - select DAC2 */
3354 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3355 /* Port-D (Line-out) mixer */
3356 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3357 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3359 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3360 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3361 /* Mono-out mixer */
3362 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3363 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3365 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3366 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3368 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3369 /* Port-B (front mic) pin */
3370 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3371 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3372 /* Port-C (rear mic) pin */
3373 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3374 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3375 /* Analog mixer; mute as default */
3376 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3377 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3378 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3379 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3380 /* Analog Mix output amp */
3381 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3382 /* SPDIF output selector */
3383 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3384 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3388 #ifdef CONFIG_SND_HDA_POWER_SAVE
3389 static struct hda_amp_list ad1884_loopbacks[] = {
3390 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3391 { 0x20, HDA_INPUT, 1 }, /* Mic */
3392 { 0x20, HDA_INPUT, 2 }, /* CD */
3393 { 0x20, HDA_INPUT, 4 }, /* Docking */
3398 static const char *ad1884_slave_vols[] = {
3399 "PCM Playback Volume",
3400 "Mic Playback Volume",
3401 "Mono Playback Volume",
3402 "Front Mic Playback Volume",
3403 "Mic Playback Volume",
3404 "CD Playback Volume",
3405 "Internal Mic Playback Volume",
3406 "Docking Mic Playback Volume",
3407 /* "Beep Playback Volume", */
3408 "IEC958 Playback Volume",
3412 static int patch_ad1884(struct hda_codec *codec)
3414 struct ad198x_spec *spec;
3417 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3423 err = snd_hda_attach_beep_device(codec, 0x10);
3428 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3430 spec->multiout.max_channels = 2;
3431 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3432 spec->multiout.dac_nids = ad1884_dac_nids;
3433 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3434 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3435 spec->adc_nids = ad1884_adc_nids;
3436 spec->capsrc_nids = ad1884_capsrc_nids;
3437 spec->input_mux = &ad1884_capture_source;
3438 spec->num_mixers = 1;
3439 spec->mixers[0] = ad1884_base_mixers;
3440 spec->num_init_verbs = 1;
3441 spec->init_verbs[0] = ad1884_init_verbs;
3442 spec->spdif_route = 0;
3443 #ifdef CONFIG_SND_HDA_POWER_SAVE
3444 spec->loopback.amplist = ad1884_loopbacks;
3446 spec->vmaster_nid = 0x04;
3447 /* we need to cover all playback volumes */
3448 spec->slave_vols = ad1884_slave_vols;
3450 codec->patch_ops = ad198x_patch_ops;
3452 codec->no_trigger_sense = 1;
3458 * Lenovo Thinkpad T61/X61
3460 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3464 { "Internal Mic", 0x1 },
3466 { "Docking-Station", 0x4 },
3472 * Dell Precision T3400
3474 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3477 { "Front Mic", 0x0 },
3484 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3485 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3486 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3487 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3488 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3489 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3490 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3491 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3492 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3493 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3494 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3495 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3496 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3497 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3498 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3499 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3500 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3501 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3502 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3503 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3505 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3506 /* The multiple "Capture Source" controls confuse alsamixer
3507 * So call somewhat different..
3509 /* .name = "Capture Source", */
3510 .name = "Input Source",
3512 .info = ad198x_mux_enum_info,
3513 .get = ad198x_mux_enum_get,
3514 .put = ad198x_mux_enum_put,
3516 /* SPDIF controls */
3517 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3519 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3520 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3521 /* identical with ad1983 */
3522 .info = ad1983_spdif_route_info,
3523 .get = ad1983_spdif_route_get,
3524 .put = ad1983_spdif_route_put,
3529 /* additional verbs */
3530 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3531 /* Port-E (docking station mic) pin */
3532 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3533 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3534 /* docking mic boost */
3535 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3536 /* Analog PC Beeper - allow firmware/ACPI beeps */
3537 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3538 /* Analog mixer - docking mic; mute as default */
3539 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3540 /* enable EAPD bit */
3541 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3546 * Dell Precision T3400
3548 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3549 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3550 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3551 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3552 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3553 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3554 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3555 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3556 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3557 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3558 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3559 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3560 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3561 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3562 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3563 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3566 /* The multiple "Capture Source" controls confuse alsamixer
3567 * So call somewhat different..
3569 /* .name = "Capture Source", */
3570 .name = "Input Source",
3572 .info = ad198x_mux_enum_info,
3573 .get = ad198x_mux_enum_get,
3574 .put = ad198x_mux_enum_put,
3579 /* Digial MIC ADC NID 0x05 + 0x06 */
3580 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3581 struct hda_codec *codec,
3582 unsigned int stream_tag,
3583 unsigned int format,
3584 struct snd_pcm_substream *substream)
3586 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3587 stream_tag, 0, format);
3591 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3592 struct hda_codec *codec,
3593 struct snd_pcm_substream *substream)
3595 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3599 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3605 .prepare = ad1984_pcm_dmic_prepare,
3606 .cleanup = ad1984_pcm_dmic_cleanup
3610 static int ad1984_build_pcms(struct hda_codec *codec)
3612 struct ad198x_spec *spec = codec->spec;
3613 struct hda_pcm *info;
3616 err = ad198x_build_pcms(codec);
3620 info = spec->pcm_rec + codec->num_pcms;
3622 info->name = "AD1984 Digital Mic";
3623 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3631 AD1984_DELL_DESKTOP,
3635 static const char *ad1984_models[AD1984_MODELS] = {
3636 [AD1984_BASIC] = "basic",
3637 [AD1984_THINKPAD] = "thinkpad",
3638 [AD1984_DELL_DESKTOP] = "dell_desktop",
3641 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3642 /* Lenovo Thinkpad T61/X61 */
3643 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3644 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3648 static int patch_ad1984(struct hda_codec *codec)
3650 struct ad198x_spec *spec;
3651 int board_config, err;
3653 err = patch_ad1884(codec);
3657 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3658 ad1984_models, ad1984_cfg_tbl);
3659 switch (board_config) {
3661 /* additional digital mics */
3662 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3663 codec->patch_ops.build_pcms = ad1984_build_pcms;
3665 case AD1984_THINKPAD:
3666 if (codec->subsystem_id == 0x17aa20fb) {
3667 /* Thinpad X300 does not have the ability to do SPDIF,
3668 or attach to docking station to use SPDIF */
3669 spec->multiout.dig_out_nid = 0;
3671 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3672 spec->input_mux = &ad1984_thinkpad_capture_source;
3673 spec->mixers[0] = ad1984_thinkpad_mixers;
3674 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3675 spec->analog_beep = 1;
3677 case AD1984_DELL_DESKTOP:
3678 spec->multiout.dig_out_nid = 0;
3679 spec->input_mux = &ad1984_dell_desktop_capture_source;
3680 spec->mixers[0] = ad1984_dell_desktop_mixers;
3688 * AD1883 / AD1884A / AD1984A / AD1984B
3690 * port-B (0x14) - front mic-in
3691 * port-E (0x1c) - rear mic-in
3692 * port-F (0x16) - CD / ext out
3693 * port-C (0x15) - rear line-in
3694 * port-D (0x12) - rear line-out
3695 * port-A (0x11) - front hp-out
3697 * AD1984A = AD1884A + digital-mic
3698 * AD1883 = equivalent with AD1984A
3699 * AD1984B = AD1984A + extra SPDIF-out
3702 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3705 static hda_nid_t ad1884a_dac_nids[1] = {
3709 #define ad1884a_adc_nids ad1884_adc_nids
3710 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3712 #define AD1884A_SPDIF_OUT 0x02
3714 static struct hda_input_mux ad1884a_capture_source = {
3717 { "Front Mic", 0x0 },
3725 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3726 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3727 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3728 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3729 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3730 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3731 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3732 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3733 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3734 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3735 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3736 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3737 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3738 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3739 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3740 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3741 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3742 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3743 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3744 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3745 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3746 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3747 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3748 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3751 /* The multiple "Capture Source" controls confuse alsamixer
3752 * So call somewhat different..
3754 /* .name = "Capture Source", */
3755 .name = "Input Source",
3757 .info = ad198x_mux_enum_info,
3758 .get = ad198x_mux_enum_get,
3759 .put = ad198x_mux_enum_put,
3761 /* SPDIF controls */
3762 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3764 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3765 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3766 /* identical with ad1983 */
3767 .info = ad1983_spdif_route_info,
3768 .get = ad1983_spdif_route_get,
3769 .put = ad1983_spdif_route_put,
3775 * initialization verbs
3777 static struct hda_verb ad1884a_init_verbs[] = {
3778 /* DACs; unmute as default */
3779 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3780 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3781 /* Port-A (HP) mixer - route only from analog mixer */
3782 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3783 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3785 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3786 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3787 /* Port-D (Line-out) mixer - route only from analog mixer */
3788 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3789 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3791 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3792 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3793 /* Mono-out mixer - route only from analog mixer */
3794 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3795 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3797 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3798 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3799 /* Port-B (front mic) pin */
3800 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3801 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3802 /* Port-C (rear line-in) pin */
3803 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3804 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3805 /* Port-E (rear mic) pin */
3806 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3807 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3808 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3809 /* Port-F (CD) pin */
3810 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3811 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3812 /* Analog mixer; mute as default */
3813 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3814 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3815 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3816 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3817 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3818 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3819 /* Analog Mix output amp */
3820 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3821 /* capture sources */
3822 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3823 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3824 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3825 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3826 /* SPDIF output amp */
3827 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3831 #ifdef CONFIG_SND_HDA_POWER_SAVE
3832 static struct hda_amp_list ad1884a_loopbacks[] = {
3833 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3834 { 0x20, HDA_INPUT, 1 }, /* Mic */
3835 { 0x20, HDA_INPUT, 2 }, /* CD */
3836 { 0x20, HDA_INPUT, 4 }, /* Docking */
3844 * Port A: Headphone jack
3846 * Port C: Internal MIC
3847 * Port D: Dock Line Out (if enabled)
3848 * Port E: Dock Line In (if enabled)
3849 * Port F: Internal speakers
3852 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3853 struct snd_ctl_elem_value *ucontrol)
3855 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3856 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3857 int mute = (!ucontrol->value.integer.value[0] &&
3858 !ucontrol->value.integer.value[1]);
3859 /* toggle GPIO1 according to the mute state */
3860 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3865 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3866 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3868 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3869 .name = "Master Playback Switch",
3870 .subdevice = HDA_SUBDEV_AMP_FLAG,
3871 .info = snd_hda_mixer_amp_switch_info,
3872 .get = snd_hda_mixer_amp_switch_get,
3873 .put = ad1884a_mobile_master_sw_put,
3874 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3876 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3877 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3878 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3879 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3880 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3881 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3882 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3883 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3884 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3885 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3886 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3887 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3888 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3889 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3893 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3894 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3895 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3897 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3898 .name = "Master Playback Switch",
3899 .subdevice = HDA_SUBDEV_AMP_FLAG,
3900 .info = snd_hda_mixer_amp_switch_info,
3901 .get = snd_hda_mixer_amp_switch_get,
3902 .put = ad1884a_mobile_master_sw_put,
3903 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3905 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3906 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3907 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3908 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3909 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3910 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3914 /* mute internal speaker if HP is plugged */
3915 static void ad1884a_hp_automute(struct hda_codec *codec)
3917 unsigned int present;
3919 present = snd_hda_jack_detect(codec, 0x11);
3920 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3921 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3922 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3923 present ? 0x00 : 0x02);
3926 /* switch to external mic if plugged */
3927 static void ad1884a_hp_automic(struct hda_codec *codec)
3929 unsigned int present;
3931 present = snd_hda_jack_detect(codec, 0x14);
3932 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3936 #define AD1884A_HP_EVENT 0x37
3937 #define AD1884A_MIC_EVENT 0x36
3939 /* unsolicited event for HP jack sensing */
3940 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3942 switch (res >> 26) {
3943 case AD1884A_HP_EVENT:
3944 ad1884a_hp_automute(codec);
3946 case AD1884A_MIC_EVENT:
3947 ad1884a_hp_automic(codec);
3952 /* initialize jack-sensing, too */
3953 static int ad1884a_hp_init(struct hda_codec *codec)
3956 ad1884a_hp_automute(codec);
3957 ad1884a_hp_automic(codec);
3961 /* mute internal speaker if HP or docking HP is plugged */
3962 static void ad1884a_laptop_automute(struct hda_codec *codec)
3964 unsigned int present;
3966 present = snd_hda_jack_detect(codec, 0x11);
3968 present = snd_hda_jack_detect(codec, 0x12);
3969 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3970 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3971 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3972 present ? 0x00 : 0x02);
3975 /* switch to external mic if plugged */
3976 static void ad1884a_laptop_automic(struct hda_codec *codec)
3980 if (snd_hda_jack_detect(codec, 0x14))
3982 else if (snd_hda_jack_detect(codec, 0x1c))
3986 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3989 /* unsolicited event for HP jack sensing */
3990 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3993 switch (res >> 26) {
3994 case AD1884A_HP_EVENT:
3995 ad1884a_laptop_automute(codec);
3997 case AD1884A_MIC_EVENT:
3998 ad1884a_laptop_automic(codec);
4003 /* initialize jack-sensing, too */
4004 static int ad1884a_laptop_init(struct hda_codec *codec)
4007 ad1884a_laptop_automute(codec);
4008 ad1884a_laptop_automic(codec);
4012 /* additional verbs for laptop model */
4013 static struct hda_verb ad1884a_laptop_verbs[] = {
4014 /* Port-A (HP) pin - always unmuted */
4015 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4016 /* Port-F (int speaker) mixer - route only from analog mixer */
4017 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4018 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4019 /* Port-F (int speaker) pin */
4020 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4021 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4022 /* required for compaq 6530s/6531s speaker output */
4023 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4024 /* Port-C pin - internal mic-in */
4025 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4026 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4027 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4028 /* Port-D (docking line-out) pin - default unmuted */
4029 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4031 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4032 /* unsolicited event for pin-sense */
4033 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4034 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4035 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4036 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4037 /* allow to touch GPIO1 (for mute control) */
4038 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4039 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4040 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4044 static struct hda_verb ad1884a_mobile_verbs[] = {
4045 /* DACs; unmute as default */
4046 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4047 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4048 /* Port-A (HP) mixer - route only from analog mixer */
4049 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4050 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4052 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4053 /* Port-A (HP) pin - always unmuted */
4054 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4055 /* Port-B (mic jack) pin */
4056 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4057 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4058 /* Port-C (int mic) pin */
4059 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4060 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4061 /* Port-F (int speaker) mixer - route only from analog mixer */
4062 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4063 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4065 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4066 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4067 /* Analog mixer; mute as default */
4068 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4069 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4070 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4071 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4072 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4073 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4074 /* Analog Mix output amp */
4075 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4076 /* capture sources */
4077 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4078 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4079 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4080 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4081 /* unsolicited event for pin-sense */
4082 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4083 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4084 /* allow to touch GPIO1 (for mute control) */
4085 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4086 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4087 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4096 * 0x17 - built-in mic
4099 static struct hda_verb ad1984a_thinkpad_verbs[] = {
4101 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4103 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4105 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4106 /* unsolicited event for pin-sense */
4107 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4108 /* internal mic - dmic */
4109 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4110 /* set magic COEFs for dmic */
4111 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4112 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4116 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4117 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4118 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4119 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4120 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4121 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4122 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4123 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4124 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4125 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4126 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4128 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4129 .name = "Capture Source",
4130 .info = ad198x_mux_enum_info,
4131 .get = ad198x_mux_enum_get,
4132 .put = ad198x_mux_enum_put,
4137 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4141 { "Internal Mic", 0x5 },
4146 /* mute internal speaker if HP is plugged */
4147 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4149 unsigned int present;
4151 present = snd_hda_jack_detect(codec, 0x11);
4152 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4153 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4156 /* unsolicited event for HP jack sensing */
4157 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4160 if ((res >> 26) != AD1884A_HP_EVENT)
4162 ad1984a_thinkpad_automute(codec);
4165 /* initialize jack-sensing, too */
4166 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4169 ad1984a_thinkpad_automute(codec);
4175 * port-A (0x11) - front hp-out
4176 * port-B (0x14) - unused
4177 * port-C (0x15) - unused
4178 * port-D (0x12) - rear line out
4179 * port-E (0x1c) - front mic-in
4180 * port-F (0x16) - Internal speakers
4181 * digital-mic (0x17) - Internal mic
4184 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4185 /* DACs; unmute as default */
4186 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4187 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4188 /* Port-A (HP) mixer - route only from analog mixer */
4189 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4190 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4192 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4193 /* Port-A (HP) pin - always unmuted */
4194 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4195 /* Port-E (int speaker) mixer - route only from analog mixer */
4196 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4198 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4199 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4200 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4201 /* Port-F (int speaker) mixer - route only from analog mixer */
4202 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4203 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4205 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4206 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4207 /* Analog mixer; mute as default */
4208 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4209 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4210 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4211 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4212 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4213 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4214 /* Analog Mix output amp */
4215 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4216 /* capture sources */
4217 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4218 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4219 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4220 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4221 /* unsolicited event for pin-sense */
4222 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4223 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4224 /* allow to touch GPIO1 (for mute control) */
4225 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4226 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4227 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4228 /* internal mic - dmic */
4229 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4230 /* set magic COEFs for dmic */
4231 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4232 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4236 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4237 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4238 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4240 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4241 .subdevice = HDA_SUBDEV_AMP_FLAG,
4242 .name = "Master Playback Switch",
4243 .info = snd_hda_mixer_amp_switch_info,
4244 .get = snd_hda_mixer_amp_switch_get,
4245 .put = ad1884a_mobile_master_sw_put,
4246 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4248 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4249 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4250 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4251 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4252 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4253 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4257 /* switch to external mic if plugged */
4258 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4260 if (snd_hda_jack_detect(codec, 0x1c))
4261 snd_hda_codec_write(codec, 0x0c, 0,
4262 AC_VERB_SET_CONNECT_SEL, 0x4);
4264 snd_hda_codec_write(codec, 0x0c, 0,
4265 AC_VERB_SET_CONNECT_SEL, 0x5);
4269 /* unsolicited event for HP jack sensing */
4270 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4273 switch (res >> 26) {
4274 case AD1884A_HP_EVENT:
4275 ad1884a_hp_automute(codec);
4277 case AD1884A_MIC_EVENT:
4278 ad1984a_touchsmart_automic(codec);
4283 /* initialize jack-sensing, too */
4284 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4287 ad1884a_hp_automute(codec);
4288 ad1984a_touchsmart_automic(codec);
4305 static const char *ad1884a_models[AD1884A_MODELS] = {
4306 [AD1884A_DESKTOP] = "desktop",
4307 [AD1884A_LAPTOP] = "laptop",
4308 [AD1884A_MOBILE] = "mobile",
4309 [AD1884A_THINKPAD] = "thinkpad",
4310 [AD1984A_TOUCHSMART] = "touchsmart",
4313 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4314 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4315 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4316 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4317 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4318 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4319 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4320 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4321 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4322 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4323 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4327 static int patch_ad1884a(struct hda_codec *codec)
4329 struct ad198x_spec *spec;
4330 int err, board_config;
4332 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4338 err = snd_hda_attach_beep_device(codec, 0x10);
4343 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4345 spec->multiout.max_channels = 2;
4346 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4347 spec->multiout.dac_nids = ad1884a_dac_nids;
4348 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4349 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4350 spec->adc_nids = ad1884a_adc_nids;
4351 spec->capsrc_nids = ad1884a_capsrc_nids;
4352 spec->input_mux = &ad1884a_capture_source;
4353 spec->num_mixers = 1;
4354 spec->mixers[0] = ad1884a_base_mixers;
4355 spec->num_init_verbs = 1;
4356 spec->init_verbs[0] = ad1884a_init_verbs;
4357 spec->spdif_route = 0;
4358 #ifdef CONFIG_SND_HDA_POWER_SAVE
4359 spec->loopback.amplist = ad1884a_loopbacks;
4361 codec->patch_ops = ad198x_patch_ops;
4363 /* override some parameters */
4364 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4367 switch (board_config) {
4368 case AD1884A_LAPTOP:
4369 spec->mixers[0] = ad1884a_laptop_mixers;
4370 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4371 spec->multiout.dig_out_nid = 0;
4372 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4373 codec->patch_ops.init = ad1884a_laptop_init;
4374 /* set the upper-limit for mixer amp to 0dB for avoiding the
4375 * possible damage by overloading
4377 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4378 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4379 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4380 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4381 (1 << AC_AMPCAP_MUTE_SHIFT));
4383 case AD1884A_MOBILE:
4384 spec->mixers[0] = ad1884a_mobile_mixers;
4385 spec->init_verbs[0] = ad1884a_mobile_verbs;
4386 spec->multiout.dig_out_nid = 0;
4387 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4388 codec->patch_ops.init = ad1884a_hp_init;
4389 /* set the upper-limit for mixer amp to 0dB for avoiding the
4390 * possible damage by overloading
4392 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4393 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4394 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4395 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4396 (1 << AC_AMPCAP_MUTE_SHIFT));
4398 case AD1884A_THINKPAD:
4399 spec->mixers[0] = ad1984a_thinkpad_mixers;
4400 spec->init_verbs[spec->num_init_verbs++] =
4401 ad1984a_thinkpad_verbs;
4402 spec->multiout.dig_out_nid = 0;
4403 spec->input_mux = &ad1984a_thinkpad_capture_source;
4404 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4405 codec->patch_ops.init = ad1984a_thinkpad_init;
4407 case AD1984A_TOUCHSMART:
4408 spec->mixers[0] = ad1984a_touchsmart_mixers;
4409 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4410 spec->multiout.dig_out_nid = 0;
4411 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4412 codec->patch_ops.init = ad1984a_touchsmart_init;
4413 /* set the upper-limit for mixer amp to 0dB for avoiding the
4414 * possible damage by overloading
4416 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4417 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4418 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4419 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4420 (1 << AC_AMPCAP_MUTE_SHIFT));
4424 codec->no_trigger_sense = 1;
4433 * port-A - front hp-out
4434 * port-B - front mic-in
4435 * port-C - rear line-in, shared surr-out (3stack)
4436 * port-D - rear line-out
4437 * port-E - rear mic-in, shared clfe-out (3stack)
4438 * port-F - rear surr-out (6stack)
4439 * port-G - rear clfe-out (6stack)
4442 static hda_nid_t ad1882_dac_nids[3] = {
4446 static hda_nid_t ad1882_adc_nids[2] = {
4450 static hda_nid_t ad1882_capsrc_nids[2] = {
4454 #define AD1882_SPDIF_OUT 0x02
4456 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4457 static struct hda_input_mux ad1882_capture_source = {
4460 { "Front Mic", 0x1 },
4468 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4469 static struct hda_input_mux ad1882a_capture_source = {
4472 { "Front Mic", 0x1 },
4475 { "Digital Mic", 0x06 },
4480 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4481 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4482 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4483 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4484 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4485 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4486 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4487 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4488 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4490 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4491 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4492 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4493 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4494 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4495 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4496 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4498 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4499 /* The multiple "Capture Source" controls confuse alsamixer
4500 * So call somewhat different..
4502 /* .name = "Capture Source", */
4503 .name = "Input Source",
4505 .info = ad198x_mux_enum_info,
4506 .get = ad198x_mux_enum_get,
4507 .put = ad198x_mux_enum_put,
4509 /* SPDIF controls */
4510 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4512 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4513 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4514 /* identical with ad1983 */
4515 .info = ad1983_spdif_route_info,
4516 .get = ad1983_spdif_route_get,
4517 .put = ad1983_spdif_route_put,
4522 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4523 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4524 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4525 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4526 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4527 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4528 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4529 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4530 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4534 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4535 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4536 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4538 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4539 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4540 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4541 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4542 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4543 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4547 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4548 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4549 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4550 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4553 .name = "Channel Mode",
4554 .info = ad198x_ch_mode_info,
4555 .get = ad198x_ch_mode_get,
4556 .put = ad198x_ch_mode_put,
4561 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4562 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4563 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4564 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4568 static struct hda_verb ad1882_ch2_init[] = {
4569 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4570 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4571 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4572 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4573 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4574 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4578 static struct hda_verb ad1882_ch4_init[] = {
4579 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4580 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4581 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4582 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4583 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4584 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4588 static struct hda_verb ad1882_ch6_init[] = {
4589 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4590 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4591 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4592 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4593 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4594 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4598 static struct hda_channel_mode ad1882_modes[3] = {
4599 { 2, ad1882_ch2_init },
4600 { 4, ad1882_ch4_init },
4601 { 6, ad1882_ch6_init },
4605 * initialization verbs
4607 static struct hda_verb ad1882_init_verbs[] = {
4608 /* DACs; mute as default */
4609 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4610 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4611 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4612 /* Port-A (HP) mixer */
4613 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4614 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4616 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4617 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4618 /* HP selector - select DAC2 */
4619 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4620 /* Port-D (Line-out) mixer */
4621 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4622 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4624 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4625 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4626 /* Mono-out mixer */
4627 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4628 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4630 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4631 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4632 /* Port-B (front mic) pin */
4633 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4634 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4635 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4636 /* Port-C (line-in) pin */
4637 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4638 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4639 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4640 /* Port-C mixer - mute as input */
4641 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4642 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4643 /* Port-E (mic-in) pin */
4644 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4645 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4646 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4647 /* Port-E mixer - mute as input */
4648 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4649 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4650 /* Port-F (surround) */
4651 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4652 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4654 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4655 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4656 /* Analog mixer; mute as default */
4657 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4658 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4659 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4660 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4661 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4662 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4663 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4664 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4665 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4666 /* Analog Mix output amp */
4667 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4668 /* SPDIF output selector */
4669 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4670 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4671 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4675 #ifdef CONFIG_SND_HDA_POWER_SAVE
4676 static struct hda_amp_list ad1882_loopbacks[] = {
4677 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4678 { 0x20, HDA_INPUT, 1 }, /* Mic */
4679 { 0x20, HDA_INPUT, 4 }, /* Line */
4680 { 0x20, HDA_INPUT, 6 }, /* CD */
4692 static const char *ad1882_models[AD1986A_MODELS] = {
4693 [AD1882_3STACK] = "3stack",
4694 [AD1882_6STACK] = "6stack",
4698 static int patch_ad1882(struct hda_codec *codec)
4700 struct ad198x_spec *spec;
4701 int err, board_config;
4703 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4709 err = snd_hda_attach_beep_device(codec, 0x10);
4714 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4716 spec->multiout.max_channels = 6;
4717 spec->multiout.num_dacs = 3;
4718 spec->multiout.dac_nids = ad1882_dac_nids;
4719 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4720 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4721 spec->adc_nids = ad1882_adc_nids;
4722 spec->capsrc_nids = ad1882_capsrc_nids;
4723 if (codec->vendor_id == 0x11d41882)
4724 spec->input_mux = &ad1882_capture_source;
4726 spec->input_mux = &ad1882a_capture_source;
4727 spec->num_mixers = 2;
4728 spec->mixers[0] = ad1882_base_mixers;
4729 if (codec->vendor_id == 0x11d41882)
4730 spec->mixers[1] = ad1882_loopback_mixers;
4732 spec->mixers[1] = ad1882a_loopback_mixers;
4733 spec->num_init_verbs = 1;
4734 spec->init_verbs[0] = ad1882_init_verbs;
4735 spec->spdif_route = 0;
4736 #ifdef CONFIG_SND_HDA_POWER_SAVE
4737 spec->loopback.amplist = ad1882_loopbacks;
4739 spec->vmaster_nid = 0x04;
4741 codec->patch_ops = ad198x_patch_ops;
4743 /* override some parameters */
4744 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4745 ad1882_models, NULL);
4746 switch (board_config) {
4749 spec->num_mixers = 3;
4750 spec->mixers[2] = ad1882_3stack_mixers;
4751 spec->channel_mode = ad1882_modes;
4752 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4753 spec->need_dac_fix = 1;
4754 spec->multiout.max_channels = 2;
4755 spec->multiout.num_dacs = 1;
4758 spec->num_mixers = 3;
4759 spec->mixers[2] = ad1882_6stack_mixers;
4763 codec->no_trigger_sense = 1;
4772 static struct hda_codec_preset snd_hda_preset_analog[] = {
4773 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4774 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4775 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4776 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4777 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4778 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4779 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4780 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4781 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4782 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4783 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4784 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4785 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4786 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4787 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4791 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4793 MODULE_LICENSE("GPL");
4794 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4796 static struct hda_codec_preset_list analog_list = {
4797 .preset = snd_hda_preset_analog,
4798 .owner = THIS_MODULE,
4801 static int __init patch_analog_init(void)
4803 return snd_hda_add_codec_preset(&analog_list);
4806 static void __exit patch_analog_exit(void)
4808 snd_hda_delete_codec_preset(&analog_list);
4811 module_init(patch_analog_init)
4812 module_exit(patch_analog_exit)