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 */
78 #ifdef CONFIG_SND_HDA_POWER_SAVE
79 struct hda_loopback_check loopback;
81 /* for virtual master */
82 hda_nid_t vmaster_nid;
83 const char **slave_vols;
84 const char **slave_sws;
88 * input MUX handling (common part)
90 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
92 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
93 struct ad198x_spec *spec = codec->spec;
95 return snd_hda_input_mux_info(spec->input_mux, uinfo);
98 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
100 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
101 struct ad198x_spec *spec = codec->spec;
102 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
104 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
108 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
111 struct ad198x_spec *spec = codec->spec;
112 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
114 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
115 spec->capsrc_nids[adc_idx],
116 &spec->cur_mux[adc_idx]);
120 * initialization (common callbacks)
122 static int ad198x_init(struct hda_codec *codec)
124 struct ad198x_spec *spec = codec->spec;
127 for (i = 0; i < spec->num_init_verbs; i++)
128 snd_hda_sequence_write(codec, spec->init_verbs[i]);
132 static const char *ad_slave_vols[] = {
133 "Front Playback Volume",
134 "Surround Playback Volume",
135 "Center Playback Volume",
136 "LFE Playback Volume",
137 "Side Playback Volume",
138 "Headphone Playback Volume",
139 "Mono Playback Volume",
140 "Speaker Playback Volume",
141 "IEC958 Playback Volume",
145 static const char *ad_slave_sws[] = {
146 "Front Playback Switch",
147 "Surround Playback Switch",
148 "Center Playback Switch",
149 "LFE Playback Switch",
150 "Side Playback Switch",
151 "Headphone Playback Switch",
152 "Mono Playback Switch",
153 "Speaker Playback Switch",
154 "IEC958 Playback Switch",
158 static void ad198x_free_kctls(struct hda_codec *codec);
160 #ifdef CONFIG_SND_HDA_INPUT_BEEP
161 /* additional beep mixers; the actual parameters are overwritten at build */
162 static struct snd_kcontrol_new ad_beep_mixer[] = {
163 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
164 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
168 #define set_beep_amp(spec, nid, idx, dir) \
169 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
171 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
174 static int ad198x_build_controls(struct hda_codec *codec)
176 struct ad198x_spec *spec = codec->spec;
177 struct snd_kcontrol *kctl;
181 for (i = 0; i < spec->num_mixers; i++) {
182 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
186 if (spec->multiout.dig_out_nid) {
187 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
190 err = snd_hda_create_spdif_share_sw(codec,
194 spec->multiout.share_spdif = 1;
196 if (spec->dig_in_nid) {
197 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
202 /* create beep controls if needed */
203 #ifdef CONFIG_SND_HDA_INPUT_BEEP
204 if (spec->beep_amp) {
205 struct snd_kcontrol_new *knew;
206 for (knew = ad_beep_mixer; knew->name; knew++) {
207 struct snd_kcontrol *kctl;
208 kctl = snd_ctl_new1(knew, codec);
211 kctl->private_value = spec->beep_amp;
212 err = snd_hda_ctl_add(codec, 0, kctl);
219 /* if we have no master control, let's create it */
220 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
221 unsigned int vmaster_tlv[4];
222 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
223 HDA_OUTPUT, vmaster_tlv);
224 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
227 spec->slave_vols : ad_slave_vols));
231 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
232 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
235 spec->slave_sws : ad_slave_sws));
240 ad198x_free_kctls(codec); /* no longer needed */
242 /* assign Capture Source enums to NID */
243 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
245 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
246 for (i = 0; kctl && i < kctl->count; i++) {
247 err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
252 /* assign IEC958 enums to NID */
253 kctl = snd_hda_find_mixer_ctl(codec,
254 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
256 err = snd_hda_add_nid(codec, kctl, 0,
257 spec->multiout.dig_out_nid);
265 #ifdef CONFIG_SND_HDA_POWER_SAVE
266 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
268 struct ad198x_spec *spec = codec->spec;
269 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
274 * Analog playback callbacks
276 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
277 struct hda_codec *codec,
278 struct snd_pcm_substream *substream)
280 struct ad198x_spec *spec = codec->spec;
281 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
285 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
286 struct hda_codec *codec,
287 unsigned int stream_tag,
289 struct snd_pcm_substream *substream)
291 struct ad198x_spec *spec = codec->spec;
292 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
296 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
297 struct hda_codec *codec,
298 struct snd_pcm_substream *substream)
300 struct ad198x_spec *spec = codec->spec;
301 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
307 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
308 struct hda_codec *codec,
309 struct snd_pcm_substream *substream)
311 struct ad198x_spec *spec = codec->spec;
312 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
315 static int ad198x_dig_playback_pcm_close(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_close(codec, &spec->multiout);
323 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
324 struct hda_codec *codec,
325 unsigned int stream_tag,
327 struct snd_pcm_substream *substream)
329 struct ad198x_spec *spec = codec->spec;
330 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
334 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
335 struct hda_codec *codec,
336 struct snd_pcm_substream *substream)
338 struct ad198x_spec *spec = codec->spec;
339 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
345 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
346 struct hda_codec *codec,
347 unsigned int stream_tag,
349 struct snd_pcm_substream *substream)
351 struct ad198x_spec *spec = codec->spec;
352 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
353 stream_tag, 0, format);
357 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
358 struct hda_codec *codec,
359 struct snd_pcm_substream *substream)
361 struct ad198x_spec *spec = codec->spec;
362 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
369 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
372 .channels_max = 6, /* changed later */
373 .nid = 0, /* fill later */
375 .open = ad198x_playback_pcm_open,
376 .prepare = ad198x_playback_pcm_prepare,
377 .cleanup = ad198x_playback_pcm_cleanup
381 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
385 .nid = 0, /* fill later */
387 .prepare = ad198x_capture_pcm_prepare,
388 .cleanup = ad198x_capture_pcm_cleanup
392 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
396 .nid = 0, /* fill later */
398 .open = ad198x_dig_playback_pcm_open,
399 .close = ad198x_dig_playback_pcm_close,
400 .prepare = ad198x_dig_playback_pcm_prepare,
401 .cleanup = ad198x_dig_playback_pcm_cleanup
405 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
409 /* NID is set in alc_build_pcms */
412 static int ad198x_build_pcms(struct hda_codec *codec)
414 struct ad198x_spec *spec = codec->spec;
415 struct hda_pcm *info = spec->pcm_rec;
418 codec->pcm_info = info;
420 info->name = "AD198x Analog";
421 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
422 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
423 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
424 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
425 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
426 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
428 if (spec->multiout.dig_out_nid) {
431 info->name = "AD198x Digital";
432 info->pcm_type = HDA_PCM_TYPE_SPDIF;
433 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
434 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
435 if (spec->dig_in_nid) {
436 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
437 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
444 static inline void ad198x_shutup(struct hda_codec *codec)
446 snd_hda_shutup_pins(codec);
449 static void ad198x_free_kctls(struct hda_codec *codec)
451 struct ad198x_spec *spec = codec->spec;
453 if (spec->kctls.list) {
454 struct snd_kcontrol_new *kctl = spec->kctls.list;
456 for (i = 0; i < spec->kctls.used; i++)
459 snd_array_free(&spec->kctls);
462 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
465 struct ad198x_spec *spec = codec->spec;
466 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
467 !spec->inv_eapd ? 0x00 : 0x02);
468 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
469 !spec->inv_eapd ? 0x00 : 0x02);
472 static void ad198x_power_eapd(struct hda_codec *codec)
474 /* We currently only handle front, HP */
475 switch (codec->vendor_id) {
484 ad198x_power_eapd_write(codec, 0x12, 0x11);
488 ad198x_power_eapd_write(codec, 0x05, 0x06);
491 ad198x_power_eapd_write(codec, 0x1b, 0x1a);
497 ad198x_power_eapd_write(codec, 0x29, 0x22);
502 static void ad198x_free(struct hda_codec *codec)
504 struct ad198x_spec *spec = codec->spec;
509 ad198x_shutup(codec);
510 ad198x_free_kctls(codec);
512 snd_hda_detach_beep_device(codec);
515 #ifdef SND_HDA_NEEDS_RESUME
516 static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
518 ad198x_shutup(codec);
519 ad198x_power_eapd(codec);
524 static struct hda_codec_ops ad198x_patch_ops = {
525 .build_controls = ad198x_build_controls,
526 .build_pcms = ad198x_build_pcms,
529 #ifdef CONFIG_SND_HDA_POWER_SAVE
530 .check_power_status = ad198x_check_power_status,
532 #ifdef SND_HDA_NEEDS_RESUME
533 .suspend = ad198x_suspend,
535 .reboot_notify = ad198x_shutup,
541 * the private value = nid
543 #define ad198x_eapd_info snd_ctl_boolean_mono_info
545 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_value *ucontrol)
548 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
549 struct ad198x_spec *spec = codec->spec;
551 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
553 ucontrol->value.integer.value[0] = spec->cur_eapd;
557 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
558 struct snd_ctl_elem_value *ucontrol)
560 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
561 struct ad198x_spec *spec = codec->spec;
562 hda_nid_t nid = kcontrol->private_value & 0xff;
564 eapd = !!ucontrol->value.integer.value[0];
567 if (eapd == spec->cur_eapd)
569 spec->cur_eapd = eapd;
570 snd_hda_codec_write_cache(codec, nid,
571 0, AC_VERB_SET_EAPD_BTLENABLE,
576 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
577 struct snd_ctl_elem_info *uinfo);
578 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
579 struct snd_ctl_elem_value *ucontrol);
580 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
581 struct snd_ctl_elem_value *ucontrol);
588 #define AD1986A_SPDIF_OUT 0x02
589 #define AD1986A_FRONT_DAC 0x03
590 #define AD1986A_SURR_DAC 0x04
591 #define AD1986A_CLFE_DAC 0x05
592 #define AD1986A_ADC 0x06
594 static hda_nid_t ad1986a_dac_nids[3] = {
595 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
597 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
598 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
600 static struct hda_input_mux ad1986a_capture_source = {
614 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
615 .ops = &snd_hda_bind_vol,
617 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
618 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
619 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
624 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
625 .ops = &snd_hda_bind_sw,
627 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
628 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
629 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
637 static struct snd_kcontrol_new ad1986a_mixers[] = {
639 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
641 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
642 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
643 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
644 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
645 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
646 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
647 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
648 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
649 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
650 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
651 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
652 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
653 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
654 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
655 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
656 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
657 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
658 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
659 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
660 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
661 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
662 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
665 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
668 .name = "Capture Source",
669 .info = ad198x_mux_enum_info,
670 .get = ad198x_mux_enum_get,
671 .put = ad198x_mux_enum_put,
673 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
677 /* additional mixers for 3stack mode */
678 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
681 .name = "Channel Mode",
682 .info = ad198x_ch_mode_info,
683 .get = ad198x_ch_mode_get,
684 .put = ad198x_ch_mode_put,
689 /* laptop model - 2ch only */
690 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
692 /* master controls both pins 0x1a and 0x1b */
693 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
694 .ops = &snd_hda_bind_vol,
696 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
697 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
702 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
703 .ops = &snd_hda_bind_sw,
705 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
706 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
711 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
712 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
713 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
714 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
715 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
716 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
717 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
718 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
719 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
720 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
721 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
722 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
723 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
724 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
726 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
727 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
728 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
729 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
731 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
732 .name = "Capture Source",
733 .info = ad198x_mux_enum_info,
734 .get = ad198x_mux_enum_get,
735 .put = ad198x_mux_enum_put,
740 /* laptop-eapd model - 2ch only */
742 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
746 { "Internal Mic", 0x4 },
751 static struct hda_input_mux ad1986a_automic_capture_source = {
759 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
760 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
761 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
765 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
766 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
767 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
768 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
769 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
770 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
771 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
772 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
774 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
775 .name = "Capture Source",
776 .info = ad198x_mux_enum_info,
777 .get = ad198x_mux_enum_get,
778 .put = ad198x_mux_enum_put,
781 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
782 .name = "External Amplifier",
783 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
784 .info = ad198x_eapd_info,
785 .get = ad198x_eapd_get,
786 .put = ad198x_eapd_put,
787 .private_value = 0x1b, /* port-D */
792 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
793 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
794 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
798 /* re-connect the mic boost input according to the jack sensing */
799 static void ad1986a_automic(struct hda_codec *codec)
801 unsigned int present;
802 present = snd_hda_jack_detect(codec, 0x1f);
803 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
804 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
808 #define AD1986A_MIC_EVENT 0x36
810 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
813 if ((res >> 26) != AD1986A_MIC_EVENT)
815 ad1986a_automic(codec);
818 static int ad1986a_automic_init(struct hda_codec *codec)
821 ad1986a_automic(codec);
825 /* laptop-automute - 2ch only */
827 static void ad1986a_update_hp(struct hda_codec *codec)
829 struct ad198x_spec *spec = codec->spec;
832 if (spec->jack_present)
833 mute = HDA_AMP_MUTE; /* mute internal speaker */
835 /* unmute internal speaker if necessary */
836 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
837 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
841 static void ad1986a_hp_automute(struct hda_codec *codec)
843 struct ad198x_spec *spec = codec->spec;
845 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
846 if (spec->inv_jack_detect)
847 spec->jack_present = !spec->jack_present;
848 ad1986a_update_hp(codec);
851 #define AD1986A_HP_EVENT 0x37
853 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
855 if ((res >> 26) != AD1986A_HP_EVENT)
857 ad1986a_hp_automute(codec);
860 static int ad1986a_hp_init(struct hda_codec *codec)
863 ad1986a_hp_automute(codec);
867 /* bind hp and internal speaker mute (with plug check) */
868 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
869 struct snd_ctl_elem_value *ucontrol)
871 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
872 long *valp = ucontrol->value.integer.value;
875 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
877 valp[0] ? 0 : HDA_AMP_MUTE);
878 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
880 valp[1] ? 0 : HDA_AMP_MUTE);
882 ad1986a_update_hp(codec);
886 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
887 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
889 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
890 .name = "Master Playback Switch",
891 .subdevice = HDA_SUBDEV_AMP_FLAG,
892 .info = snd_hda_mixer_amp_switch_info,
893 .get = snd_hda_mixer_amp_switch_get,
894 .put = ad1986a_hp_master_sw_put,
895 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
902 * initialization verbs
904 static struct hda_verb ad1986a_init_verbs[] = {
905 /* Front, Surround, CLFE DAC; mute as default */
906 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
907 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
908 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
910 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
911 /* HP, Line-Out, Surround, CLFE selectors */
912 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
913 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
914 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
915 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
917 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
918 /* Mic selector: Mic 1/2 pin */
919 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
920 /* Line-in selector: Line-in */
921 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
923 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
924 /* Record selector: mic */
925 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
926 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
927 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
928 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
929 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
930 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
931 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
933 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
934 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
935 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
936 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
937 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
938 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
939 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
941 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
942 /* Front, Surround, CLFE Pins */
943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
944 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
945 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
947 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
949 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
950 /* Line, Aux, CD, Beep-In Pin */
951 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
952 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
953 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
954 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
955 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
959 static struct hda_verb ad1986a_ch2_init[] = {
960 /* Surround out -> Line In */
961 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
962 /* Line-in selectors */
963 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
965 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
966 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
967 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
971 static struct hda_verb ad1986a_ch4_init[] = {
972 /* Surround out -> Surround */
973 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
974 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
976 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
977 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
981 static struct hda_verb ad1986a_ch6_init[] = {
982 /* Surround out -> Surround out */
983 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
984 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
986 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
987 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
991 static struct hda_channel_mode ad1986a_modes[3] = {
992 { 2, ad1986a_ch2_init },
993 { 4, ad1986a_ch4_init },
994 { 6, ad1986a_ch6_init },
997 /* eapd initialization */
998 static struct hda_verb ad1986a_eapd_init_verbs[] = {
999 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1003 static struct hda_verb ad1986a_automic_verbs[] = {
1004 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1005 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1006 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1007 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1008 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1012 /* Ultra initialization */
1013 static struct hda_verb ad1986a_ultra_init[] = {
1014 /* eapd initialization */
1015 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1016 /* CLFE -> Mic in */
1017 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1018 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1019 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1023 /* pin sensing on HP jack */
1024 static struct hda_verb ad1986a_hp_init_verbs[] = {
1025 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1029 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1032 switch (res >> 26) {
1033 case AD1986A_HP_EVENT:
1034 ad1986a_hp_automute(codec);
1036 case AD1986A_MIC_EVENT:
1037 ad1986a_automic(codec);
1042 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1045 ad1986a_hp_automute(codec);
1046 ad1986a_automic(codec);
1056 AD1986A_LAPTOP_EAPD,
1057 AD1986A_LAPTOP_AUTOMUTE,
1060 AD1986A_SAMSUNG_P50,
1064 static const char *ad1986a_models[AD1986A_MODELS] = {
1065 [AD1986A_6STACK] = "6stack",
1066 [AD1986A_3STACK] = "3stack",
1067 [AD1986A_LAPTOP] = "laptop",
1068 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1069 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1070 [AD1986A_ULTRA] = "ultra",
1071 [AD1986A_SAMSUNG] = "samsung",
1072 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1075 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1076 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1077 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1078 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1079 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1080 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1081 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1082 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1083 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1084 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1085 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1086 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1087 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1088 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1089 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1090 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1091 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1092 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1093 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1094 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1095 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1096 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1097 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1098 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1099 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1100 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1101 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1102 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1106 #ifdef CONFIG_SND_HDA_POWER_SAVE
1107 static struct hda_amp_list ad1986a_loopbacks[] = {
1108 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1109 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1110 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1111 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1112 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1117 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1119 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1120 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1123 static int patch_ad1986a(struct hda_codec *codec)
1125 struct ad198x_spec *spec;
1126 int err, board_config;
1128 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1134 err = snd_hda_attach_beep_device(codec, 0x19);
1139 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1141 spec->multiout.max_channels = 6;
1142 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1143 spec->multiout.dac_nids = ad1986a_dac_nids;
1144 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1145 spec->num_adc_nids = 1;
1146 spec->adc_nids = ad1986a_adc_nids;
1147 spec->capsrc_nids = ad1986a_capsrc_nids;
1148 spec->input_mux = &ad1986a_capture_source;
1149 spec->num_mixers = 1;
1150 spec->mixers[0] = ad1986a_mixers;
1151 spec->num_init_verbs = 1;
1152 spec->init_verbs[0] = ad1986a_init_verbs;
1153 #ifdef CONFIG_SND_HDA_POWER_SAVE
1154 spec->loopback.amplist = ad1986a_loopbacks;
1156 spec->vmaster_nid = 0x1b;
1157 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1159 codec->patch_ops = ad198x_patch_ops;
1161 /* override some parameters */
1162 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1165 switch (board_config) {
1166 case AD1986A_3STACK:
1167 spec->num_mixers = 2;
1168 spec->mixers[1] = ad1986a_3st_mixers;
1169 spec->num_init_verbs = 2;
1170 spec->init_verbs[1] = ad1986a_ch2_init;
1171 spec->channel_mode = ad1986a_modes;
1172 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1173 spec->need_dac_fix = 1;
1174 spec->multiout.max_channels = 2;
1175 spec->multiout.num_dacs = 1;
1177 case AD1986A_LAPTOP:
1178 spec->mixers[0] = ad1986a_laptop_mixers;
1179 spec->multiout.max_channels = 2;
1180 spec->multiout.num_dacs = 1;
1181 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1183 case AD1986A_LAPTOP_EAPD:
1184 spec->num_mixers = 3;
1185 spec->mixers[0] = ad1986a_laptop_master_mixers;
1186 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1187 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1188 spec->num_init_verbs = 2;
1189 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1190 spec->multiout.max_channels = 2;
1191 spec->multiout.num_dacs = 1;
1192 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1193 if (!is_jack_available(codec, 0x25))
1194 spec->multiout.dig_out_nid = 0;
1195 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1197 case AD1986A_SAMSUNG:
1198 spec->num_mixers = 2;
1199 spec->mixers[0] = ad1986a_laptop_master_mixers;
1200 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1201 spec->num_init_verbs = 3;
1202 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1203 spec->init_verbs[2] = ad1986a_automic_verbs;
1204 spec->multiout.max_channels = 2;
1205 spec->multiout.num_dacs = 1;
1206 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1207 if (!is_jack_available(codec, 0x25))
1208 spec->multiout.dig_out_nid = 0;
1209 spec->input_mux = &ad1986a_automic_capture_source;
1210 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1211 codec->patch_ops.init = ad1986a_automic_init;
1213 case AD1986A_SAMSUNG_P50:
1214 spec->num_mixers = 2;
1215 spec->mixers[0] = ad1986a_automute_master_mixers;
1216 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1217 spec->num_init_verbs = 4;
1218 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1219 spec->init_verbs[2] = ad1986a_automic_verbs;
1220 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1221 spec->multiout.max_channels = 2;
1222 spec->multiout.num_dacs = 1;
1223 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1224 if (!is_jack_available(codec, 0x25))
1225 spec->multiout.dig_out_nid = 0;
1226 spec->input_mux = &ad1986a_automic_capture_source;
1227 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1228 codec->patch_ops.init = ad1986a_samsung_p50_init;
1230 case AD1986A_LAPTOP_AUTOMUTE:
1231 spec->num_mixers = 3;
1232 spec->mixers[0] = ad1986a_automute_master_mixers;
1233 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1234 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1235 spec->num_init_verbs = 3;
1236 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1237 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1238 spec->multiout.max_channels = 2;
1239 spec->multiout.num_dacs = 1;
1240 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1241 if (!is_jack_available(codec, 0x25))
1242 spec->multiout.dig_out_nid = 0;
1243 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1244 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1245 codec->patch_ops.init = ad1986a_hp_init;
1246 /* Lenovo N100 seems to report the reversed bit
1247 * for HP jack-sensing
1249 spec->inv_jack_detect = 1;
1252 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1253 spec->num_init_verbs = 2;
1254 spec->init_verbs[1] = ad1986a_ultra_init;
1255 spec->multiout.max_channels = 2;
1256 spec->multiout.num_dacs = 1;
1257 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1258 spec->multiout.dig_out_nid = 0;
1262 /* AD1986A has a hardware problem that it can't share a stream
1263 * with multiple output pins. The copy of front to surrounds
1264 * causes noisy or silent outputs at a certain timing, e.g.
1265 * changing the volume.
1266 * So, let's disable the shared stream.
1268 spec->multiout.no_share_stream = 1;
1270 codec->no_trigger_sense = 1;
1279 #define AD1983_SPDIF_OUT 0x02
1280 #define AD1983_DAC 0x03
1281 #define AD1983_ADC 0x04
1283 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1284 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1285 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1287 static struct hda_input_mux ad1983_capture_source = {
1293 { "Mix Mono", 0x3 },
1298 * SPDIF playback route
1300 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1302 static char *texts[] = { "PCM", "ADC" };
1304 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1306 uinfo->value.enumerated.items = 2;
1307 if (uinfo->value.enumerated.item > 1)
1308 uinfo->value.enumerated.item = 1;
1309 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1313 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1315 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1316 struct ad198x_spec *spec = codec->spec;
1318 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1322 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1324 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1325 struct ad198x_spec *spec = codec->spec;
1327 if (ucontrol->value.enumerated.item[0] > 1)
1329 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1330 spec->spdif_route = ucontrol->value.enumerated.item[0];
1331 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1332 AC_VERB_SET_CONNECT_SEL,
1339 static struct snd_kcontrol_new ad1983_mixers[] = {
1340 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1341 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1342 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1343 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1344 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1345 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1346 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1347 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1348 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1349 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1350 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1351 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1352 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1353 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1354 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1356 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1357 .name = "Capture Source",
1358 .info = ad198x_mux_enum_info,
1359 .get = ad198x_mux_enum_get,
1360 .put = ad198x_mux_enum_put,
1363 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1364 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1365 .info = ad1983_spdif_route_info,
1366 .get = ad1983_spdif_route_get,
1367 .put = ad1983_spdif_route_put,
1372 static struct hda_verb ad1983_init_verbs[] = {
1373 /* Front, HP, Mono; mute as default */
1374 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1375 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1376 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1377 /* Beep, PCM, Mic, Line-In: mute */
1378 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1379 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1380 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1381 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1382 /* Front, HP selectors; from Mix */
1383 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1384 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1385 /* Mono selector; from Mix */
1386 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1387 /* Mic selector; Mic */
1388 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1389 /* Line-in selector: Line-in */
1390 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1391 /* Mic boost: 0dB */
1392 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1393 /* Record selector: mic */
1394 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1395 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1396 /* SPDIF route: PCM */
1397 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1399 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1401 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1403 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1405 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1407 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1411 #ifdef CONFIG_SND_HDA_POWER_SAVE
1412 static struct hda_amp_list ad1983_loopbacks[] = {
1413 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1414 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1419 static int patch_ad1983(struct hda_codec *codec)
1421 struct ad198x_spec *spec;
1424 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1430 err = snd_hda_attach_beep_device(codec, 0x10);
1435 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1437 spec->multiout.max_channels = 2;
1438 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1439 spec->multiout.dac_nids = ad1983_dac_nids;
1440 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1441 spec->num_adc_nids = 1;
1442 spec->adc_nids = ad1983_adc_nids;
1443 spec->capsrc_nids = ad1983_capsrc_nids;
1444 spec->input_mux = &ad1983_capture_source;
1445 spec->num_mixers = 1;
1446 spec->mixers[0] = ad1983_mixers;
1447 spec->num_init_verbs = 1;
1448 spec->init_verbs[0] = ad1983_init_verbs;
1449 spec->spdif_route = 0;
1450 #ifdef CONFIG_SND_HDA_POWER_SAVE
1451 spec->loopback.amplist = ad1983_loopbacks;
1453 spec->vmaster_nid = 0x05;
1455 codec->patch_ops = ad198x_patch_ops;
1457 codec->no_trigger_sense = 1;
1464 * AD1981 HD specific
1467 #define AD1981_SPDIF_OUT 0x02
1468 #define AD1981_DAC 0x03
1469 #define AD1981_ADC 0x04
1471 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1472 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1473 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1475 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1476 static struct hda_input_mux ad1981_capture_source = {
1479 { "Front Mic", 0x0 },
1482 { "Mix Mono", 0x3 },
1489 static struct snd_kcontrol_new ad1981_mixers[] = {
1490 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1491 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1492 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1493 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1494 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1495 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1496 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1497 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1498 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1499 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1500 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1507 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1509 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1510 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1514 .name = "Capture Source",
1515 .info = ad198x_mux_enum_info,
1516 .get = ad198x_mux_enum_get,
1517 .put = ad198x_mux_enum_put,
1519 /* identical with AD1983 */
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1523 .info = ad1983_spdif_route_info,
1524 .get = ad1983_spdif_route_get,
1525 .put = ad1983_spdif_route_put,
1530 static struct hda_verb ad1981_init_verbs[] = {
1531 /* Front, HP, Mono; mute as default */
1532 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1533 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1534 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1535 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1536 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1537 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1538 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1539 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1540 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1541 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1542 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1543 /* Front, HP selectors; from Mix */
1544 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1545 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1546 /* Mono selector; from Mix */
1547 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1548 /* Mic Mixer; select Front Mic */
1549 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1550 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1551 /* Mic boost: 0dB */
1552 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1553 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1554 /* Record selector: Front mic */
1555 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1556 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1557 /* SPDIF route: PCM */
1558 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1560 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1562 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1564 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1565 /* Front & Rear Mic Pins */
1566 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1567 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1569 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1571 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1572 /* Line-Out as Input: disabled */
1573 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1577 #ifdef CONFIG_SND_HDA_POWER_SAVE
1578 static struct hda_amp_list ad1981_loopbacks[] = {
1579 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1580 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1581 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1582 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1583 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1589 * Patch for HP nx6320
1591 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1592 * speaker output enabled _and_ mute-LED off.
1595 #define AD1981_HP_EVENT 0x37
1596 #define AD1981_MIC_EVENT 0x38
1598 static struct hda_verb ad1981_hp_init_verbs[] = {
1599 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1600 /* pin sensing on HP and Mic jacks */
1601 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1602 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1606 /* turn on/off EAPD (+ mute HP) as a master switch */
1607 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1608 struct snd_ctl_elem_value *ucontrol)
1610 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1611 struct ad198x_spec *spec = codec->spec;
1613 if (! ad198x_eapd_put(kcontrol, ucontrol))
1615 /* change speaker pin appropriately */
1616 snd_hda_codec_write(codec, 0x05, 0,
1617 AC_VERB_SET_PIN_WIDGET_CONTROL,
1618 spec->cur_eapd ? PIN_OUT : 0);
1619 /* toggle HP mute appropriately */
1620 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1622 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1626 /* bind volumes of both NID 0x05 and 0x06 */
1627 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1628 .ops = &snd_hda_bind_vol,
1630 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1631 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1636 /* mute internal speaker if HP is plugged */
1637 static void ad1981_hp_automute(struct hda_codec *codec)
1639 unsigned int present;
1641 present = snd_hda_jack_detect(codec, 0x06);
1642 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1643 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1646 /* toggle input of built-in and mic jack appropriately */
1647 static void ad1981_hp_automic(struct hda_codec *codec)
1649 static struct hda_verb mic_jack_on[] = {
1650 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1651 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1654 static struct hda_verb mic_jack_off[] = {
1655 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1656 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1659 unsigned int present;
1661 present = snd_hda_jack_detect(codec, 0x08);
1663 snd_hda_sequence_write(codec, mic_jack_on);
1665 snd_hda_sequence_write(codec, mic_jack_off);
1668 /* unsolicited event for HP jack sensing */
1669 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1674 case AD1981_HP_EVENT:
1675 ad1981_hp_automute(codec);
1677 case AD1981_MIC_EVENT:
1678 ad1981_hp_automic(codec);
1683 static struct hda_input_mux ad1981_hp_capture_source = {
1687 { "Docking-Station", 0x1 },
1692 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1693 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1695 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1696 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1697 .name = "Master Playback Switch",
1698 .info = ad198x_eapd_info,
1699 .get = ad198x_eapd_get,
1700 .put = ad1981_hp_master_sw_put,
1701 .private_value = 0x05,
1703 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1704 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1706 /* FIXME: analog mic/line loopback doesn't work with my tests...
1707 * (although recording is OK)
1709 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1710 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1711 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1712 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1713 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1714 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1715 /* FIXME: does this laptop have analog CD connection? */
1716 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1717 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1719 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1720 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1721 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1722 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1725 .name = "Capture Source",
1726 .info = ad198x_mux_enum_info,
1727 .get = ad198x_mux_enum_get,
1728 .put = ad198x_mux_enum_put,
1733 /* initialize jack-sensing, too */
1734 static int ad1981_hp_init(struct hda_codec *codec)
1737 ad1981_hp_automute(codec);
1738 ad1981_hp_automic(codec);
1742 /* configuration for Toshiba Laptops */
1743 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1744 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1745 /* pin sensing on HP and Mic jacks */
1746 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1747 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1751 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1752 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1753 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1757 /* configuration for Lenovo Thinkpad T60 */
1758 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1759 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1760 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1761 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1762 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1763 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1764 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1765 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1766 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1767 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1768 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1769 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1772 .name = "Capture Source",
1773 .info = ad198x_mux_enum_info,
1774 .get = ad198x_mux_enum_get,
1775 .put = ad198x_mux_enum_put,
1777 /* identical with AD1983 */
1779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1781 .info = ad1983_spdif_route_info,
1782 .get = ad1983_spdif_route_get,
1783 .put = ad1983_spdif_route_put,
1788 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1806 static const char *ad1981_models[AD1981_MODELS] = {
1808 [AD1981_THINKPAD] = "thinkpad",
1809 [AD1981_BASIC] = "basic",
1810 [AD1981_TOSHIBA] = "toshiba"
1813 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1814 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1815 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1817 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1818 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1819 /* Lenovo Thinkpad T60/X60/Z6xx */
1820 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1821 /* HP nx6320 (reversed SSID, H/W bug) */
1822 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1826 static int patch_ad1981(struct hda_codec *codec)
1828 struct ad198x_spec *spec;
1829 int err, board_config;
1831 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1837 err = snd_hda_attach_beep_device(codec, 0x10);
1842 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1844 spec->multiout.max_channels = 2;
1845 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1846 spec->multiout.dac_nids = ad1981_dac_nids;
1847 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1848 spec->num_adc_nids = 1;
1849 spec->adc_nids = ad1981_adc_nids;
1850 spec->capsrc_nids = ad1981_capsrc_nids;
1851 spec->input_mux = &ad1981_capture_source;
1852 spec->num_mixers = 1;
1853 spec->mixers[0] = ad1981_mixers;
1854 spec->num_init_verbs = 1;
1855 spec->init_verbs[0] = ad1981_init_verbs;
1856 spec->spdif_route = 0;
1857 #ifdef CONFIG_SND_HDA_POWER_SAVE
1858 spec->loopback.amplist = ad1981_loopbacks;
1860 spec->vmaster_nid = 0x05;
1862 codec->patch_ops = ad198x_patch_ops;
1864 /* override some parameters */
1865 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1868 switch (board_config) {
1870 spec->mixers[0] = ad1981_hp_mixers;
1871 spec->num_init_verbs = 2;
1872 spec->init_verbs[1] = ad1981_hp_init_verbs;
1873 spec->multiout.dig_out_nid = 0;
1874 spec->input_mux = &ad1981_hp_capture_source;
1876 codec->patch_ops.init = ad1981_hp_init;
1877 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1878 /* set the upper-limit for mixer amp to 0dB for avoiding the
1879 * possible damage by overloading
1881 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1882 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1883 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1884 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1885 (1 << AC_AMPCAP_MUTE_SHIFT));
1887 case AD1981_THINKPAD:
1888 spec->mixers[0] = ad1981_thinkpad_mixers;
1889 spec->input_mux = &ad1981_thinkpad_capture_source;
1890 /* set the upper-limit for mixer amp to 0dB for avoiding the
1891 * possible damage by overloading
1893 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1894 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1895 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1896 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1897 (1 << AC_AMPCAP_MUTE_SHIFT));
1899 case AD1981_TOSHIBA:
1900 spec->mixers[0] = ad1981_hp_mixers;
1901 spec->mixers[1] = ad1981_toshiba_mixers;
1902 spec->num_init_verbs = 2;
1903 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1904 spec->multiout.dig_out_nid = 0;
1905 spec->input_mux = &ad1981_hp_capture_source;
1906 codec->patch_ops.init = ad1981_hp_init;
1907 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1911 codec->no_trigger_sense = 1;
1920 * Output pins and routes
1922 * Pin Mix Sel DAC (*)
1923 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1924 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1925 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1926 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1927 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1928 * port-F 0x16 (mute) <- 0x2a <- 06
1929 * port-G 0x24 (mute) <- 0x27 <- 05
1930 * port-H 0x25 (mute) <- 0x28 <- 0a
1931 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1933 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1934 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1936 * Input pins and routes
1938 * pin boost mix input # / adc input #
1939 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1940 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1941 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1942 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1943 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1944 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1945 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1946 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1950 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1951 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1953 * Inputs of Analog Mix (0x20)
1954 * 0:Port-B (front mic)
1955 * 1:Port-C/G/H (line-in)
1957 * 3:Port-D (line-in/2)
1958 * 4:Port-E/G/H (mic-in)
1959 * 5:Port-F (mic2-in)
1965 * 1:Port-B (front mic-in)
1966 * 2:Port-C (line-in)
1967 * 3:Port-F (mic2-in)
1972 * 8:Port-D (line-in/2)
1975 * Proposed pin assignments by the datasheet
1978 * Port-A front headphone
1988 * Port-A front headphone
1990 * C rear line-in/surround
1992 * E rear mic-in/CLFE
1998 * D internal speaker (with EAPD)
1999 * E/F quad mic array
2015 /* reivision id to check workarounds */
2016 #define AD1988A_REV2 0x100200
2018 #define is_rev2(codec) \
2019 ((codec)->vendor_id == 0x11d41988 && \
2020 (codec)->revision_id == AD1988A_REV2)
2026 static hda_nid_t ad1988_6stack_dac_nids[4] = {
2027 0x04, 0x06, 0x05, 0x0a
2030 static hda_nid_t ad1988_3stack_dac_nids[3] = {
2034 /* for AD1988A revision-2, DAC2-4 are swapped */
2035 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2036 0x04, 0x05, 0x0a, 0x06
2039 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2043 static hda_nid_t ad1988_adc_nids[3] = {
2047 static hda_nid_t ad1988_capsrc_nids[3] = {
2051 #define AD1988_SPDIF_OUT 0x02
2052 #define AD1988_SPDIF_OUT_HDMI 0x0b
2053 #define AD1988_SPDIF_IN 0x07
2055 static hda_nid_t ad1989b_slave_dig_outs[] = {
2056 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2059 static struct hda_input_mux ad1988_6stack_capture_source = {
2062 { "Front Mic", 0x1 }, /* port-B */
2063 { "Line", 0x2 }, /* port-C */
2064 { "Mic", 0x4 }, /* port-E */
2070 static struct hda_input_mux ad1988_laptop_capture_source = {
2073 { "Mic/Line", 0x1 }, /* port-B */
2081 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2082 struct snd_ctl_elem_info *uinfo)
2084 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2085 struct ad198x_spec *spec = codec->spec;
2086 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2087 spec->num_channel_mode);
2090 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2091 struct snd_ctl_elem_value *ucontrol)
2093 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2094 struct ad198x_spec *spec = codec->spec;
2095 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2096 spec->num_channel_mode, spec->multiout.max_channels);
2099 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2100 struct snd_ctl_elem_value *ucontrol)
2102 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2103 struct ad198x_spec *spec = codec->spec;
2104 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2105 spec->num_channel_mode,
2106 &spec->multiout.max_channels);
2107 if (err >= 0 && spec->need_dac_fix)
2108 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2113 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2114 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2115 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2116 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2117 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2118 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2122 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2123 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2124 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2125 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2126 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2127 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2131 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2132 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2133 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2134 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2135 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2136 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2137 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2138 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2140 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2141 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2142 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2143 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2144 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2145 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2146 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2147 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2149 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2150 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2152 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2153 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2159 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2160 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2161 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2162 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2163 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2167 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
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", 0x06, 1, 0x0, HDA_OUTPUT),
2171 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2175 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2176 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2177 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2178 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2179 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2180 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2181 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2183 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2184 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2185 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2186 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2187 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2188 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2189 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2190 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2192 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2193 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2195 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2196 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2198 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2199 .name = "Channel Mode",
2200 .info = ad198x_ch_mode_info,
2201 .get = ad198x_ch_mode_get,
2202 .put = ad198x_ch_mode_put,
2209 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2210 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2211 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2212 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2214 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2215 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2216 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2217 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2218 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2219 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2221 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2222 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2224 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2228 .name = "External Amplifier",
2229 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2230 .info = ad198x_eapd_info,
2231 .get = ad198x_eapd_get,
2232 .put = ad198x_eapd_put,
2233 .private_value = 0x12, /* port-D */
2240 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2241 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2242 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2243 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2244 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2245 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2246 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2248 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2249 /* The multiple "Capture Source" controls confuse alsamixer
2250 * So call somewhat different..
2252 /* .name = "Capture Source", */
2253 .name = "Input Source",
2255 .info = ad198x_mux_enum_info,
2256 .get = ad198x_mux_enum_get,
2257 .put = ad198x_mux_enum_put,
2262 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2263 struct snd_ctl_elem_info *uinfo)
2265 static char *texts[] = {
2266 "PCM", "ADC1", "ADC2", "ADC3"
2268 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2270 uinfo->value.enumerated.items = 4;
2271 if (uinfo->value.enumerated.item >= 4)
2272 uinfo->value.enumerated.item = 3;
2273 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2277 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2278 struct snd_ctl_elem_value *ucontrol)
2280 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2283 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2286 ucontrol->value.enumerated.item[0] = 0;
2288 sel = snd_hda_codec_read(codec, 0x0b, 0,
2289 AC_VERB_GET_CONNECT_SEL, 0);
2294 ucontrol->value.enumerated.item[0] = sel;
2299 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2300 struct snd_ctl_elem_value *ucontrol)
2302 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2303 unsigned int val, sel;
2306 val = ucontrol->value.enumerated.item[0];
2310 sel = snd_hda_codec_read(codec, 0x1d, 0,
2311 AC_VERB_GET_AMP_GAIN_MUTE,
2313 change = sel & 0x80;
2315 snd_hda_codec_write_cache(codec, 0x1d, 0,
2316 AC_VERB_SET_AMP_GAIN_MUTE,
2318 snd_hda_codec_write_cache(codec, 0x1d, 0,
2319 AC_VERB_SET_AMP_GAIN_MUTE,
2323 sel = snd_hda_codec_read(codec, 0x1d, 0,
2324 AC_VERB_GET_AMP_GAIN_MUTE,
2325 AC_AMP_GET_INPUT | 0x01);
2326 change = sel & 0x80;
2328 snd_hda_codec_write_cache(codec, 0x1d, 0,
2329 AC_VERB_SET_AMP_GAIN_MUTE,
2331 snd_hda_codec_write_cache(codec, 0x1d, 0,
2332 AC_VERB_SET_AMP_GAIN_MUTE,
2335 sel = snd_hda_codec_read(codec, 0x0b, 0,
2336 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2337 change |= sel != val;
2339 snd_hda_codec_write_cache(codec, 0x0b, 0,
2340 AC_VERB_SET_CONNECT_SEL,
2346 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2347 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2349 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2350 .name = "IEC958 Playback Source",
2351 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2352 .info = ad1988_spdif_playback_source_info,
2353 .get = ad1988_spdif_playback_source_get,
2354 .put = ad1988_spdif_playback_source_put,
2359 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2360 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2364 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2365 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2366 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2371 * initialization verbs
2375 * for 6-stack (+dig)
2377 static struct hda_verb ad1988_6stack_init_verbs[] = {
2378 /* Front, Surround, CLFE, side DAC; unmute as default */
2379 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2380 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2381 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2382 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2383 /* Port-A front headphon path */
2384 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2385 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2386 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2387 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2388 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2389 /* Port-D line-out path */
2390 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2391 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2392 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2393 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2394 /* Port-F surround path */
2395 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2396 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2397 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2398 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2399 /* Port-G CLFE path */
2400 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2401 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2402 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2403 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2404 /* Port-H side path */
2405 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2406 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2407 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2408 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2410 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2411 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2412 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2413 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2414 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2415 /* Port-B front mic-in path */
2416 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2417 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2418 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2419 /* Port-C line-in path */
2420 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2421 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2422 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2423 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2424 /* Port-E mic-in path */
2425 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2426 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2427 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2428 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2429 /* Analog CD Input */
2430 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2431 /* Analog Mix output amp */
2432 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2437 static struct hda_verb ad1988_capture_init_verbs[] = {
2438 /* mute analog mix */
2439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2441 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2442 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2443 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2444 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2445 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2446 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2447 /* select ADCs - front-mic */
2448 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2449 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2450 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2455 static struct hda_verb ad1988_spdif_init_verbs[] = {
2457 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2458 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2459 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2460 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2462 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2467 static struct hda_verb ad1988_spdif_in_init_verbs[] = {
2468 /* unmute SPDIF input pin */
2469 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2473 /* AD1989 has no ADC -> SPDIF route */
2474 static struct hda_verb ad1989_spdif_init_verbs[] = {
2475 /* SPDIF-1 out pin */
2476 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2477 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2478 /* SPDIF-2/HDMI out pin */
2479 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2480 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2485 * verbs for 3stack (+dig)
2487 static struct hda_verb ad1988_3stack_ch2_init[] = {
2488 /* set port-C to line-in */
2489 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2490 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2491 /* set port-E to mic-in */
2492 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2493 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2497 static struct hda_verb ad1988_3stack_ch6_init[] = {
2498 /* set port-C to surround out */
2499 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2500 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2501 /* set port-E to CLFE out */
2502 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2503 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2507 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2508 { 2, ad1988_3stack_ch2_init },
2509 { 6, ad1988_3stack_ch6_init },
2512 static struct hda_verb ad1988_3stack_init_verbs[] = {
2513 /* Front, Surround, CLFE, side DAC; unmute as default */
2514 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2515 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2516 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2517 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2518 /* Port-A front headphon path */
2519 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2520 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2521 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2522 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2523 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2524 /* Port-D line-out path */
2525 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2526 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2527 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2528 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2530 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2531 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2532 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2533 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2534 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2535 /* Port-B front mic-in path */
2536 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2537 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2538 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2539 /* Port-C line-in/surround path - 6ch mode as default */
2540 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2541 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2542 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2543 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2544 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2545 /* Port-E mic-in/CLFE path - 6ch mode as default */
2546 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2547 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2548 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2549 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2550 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2551 /* mute analog mix */
2552 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2553 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2554 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2555 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2556 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2557 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2558 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2559 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2560 /* select ADCs - front-mic */
2561 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2562 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2563 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2564 /* Analog Mix output amp */
2565 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2570 * verbs for laptop mode (+dig)
2572 static struct hda_verb ad1988_laptop_hp_on[] = {
2573 /* unmute port-A and mute port-D */
2574 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2575 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2578 static struct hda_verb ad1988_laptop_hp_off[] = {
2579 /* mute port-A and unmute port-D */
2580 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2581 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2585 #define AD1988_HP_EVENT 0x01
2587 static struct hda_verb ad1988_laptop_init_verbs[] = {
2588 /* Front, Surround, CLFE, side DAC; unmute as default */
2589 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2590 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2591 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2592 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2593 /* Port-A front headphon path */
2594 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2595 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2596 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2597 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2598 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2599 /* unsolicited event for pin-sense */
2600 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2601 /* Port-D line-out path + EAPD */
2602 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2603 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2604 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2605 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2606 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2608 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2609 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2610 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2611 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2612 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2613 /* Port-B mic-in path */
2614 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2615 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2616 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2617 /* Port-C docking station - try to output */
2618 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2619 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2620 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2621 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2622 /* mute analog mix */
2623 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2624 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2625 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2626 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2627 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2628 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2631 /* select ADCs - mic */
2632 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2633 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2634 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2635 /* Analog Mix output amp */
2636 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2640 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2642 if ((res >> 26) != AD1988_HP_EVENT)
2644 if (snd_hda_jack_detect(codec, 0x11))
2645 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2647 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2650 #ifdef CONFIG_SND_HDA_POWER_SAVE
2651 static struct hda_amp_list ad1988_loopbacks[] = {
2652 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2653 { 0x20, HDA_INPUT, 1 }, /* Line */
2654 { 0x20, HDA_INPUT, 4 }, /* Mic */
2655 { 0x20, HDA_INPUT, 6 }, /* CD */
2661 * Automatic parse of I/O pins from the BIOS configuration
2669 static struct snd_kcontrol_new ad1988_control_templates[] = {
2670 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2671 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2672 HDA_BIND_MUTE(NULL, 0, 0, 0),
2675 /* add dynamic controls */
2676 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2679 struct snd_kcontrol_new *knew;
2681 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2682 knew = snd_array_new(&spec->kctls);
2685 *knew = ad1988_control_templates[type];
2686 knew->name = kstrdup(name, GFP_KERNEL);
2689 if (get_amp_nid_(val))
2690 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2691 knew->private_value = val;
2695 #define AD1988_PIN_CD_NID 0x18
2696 #define AD1988_PIN_BEEP_NID 0x10
2698 static hda_nid_t ad1988_mixer_nids[8] = {
2699 /* A B C D E F G H */
2700 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2703 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2705 static hda_nid_t idx_to_dac[8] = {
2706 /* A B C D E F G H */
2707 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2709 static hda_nid_t idx_to_dac_rev2[8] = {
2710 /* A B C D E F G H */
2711 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2714 return idx_to_dac_rev2[idx];
2716 return idx_to_dac[idx];
2719 static hda_nid_t ad1988_boost_nids[8] = {
2720 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2723 static int ad1988_pin_idx(hda_nid_t nid)
2725 static hda_nid_t ad1988_io_pins[8] = {
2726 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2729 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2730 if (ad1988_io_pins[i] == nid)
2732 return 0; /* should be -1 */
2735 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2737 static int loopback_idx[8] = {
2738 2, 0, 1, 3, 4, 5, 1, 4
2741 case AD1988_PIN_CD_NID:
2744 return loopback_idx[ad1988_pin_idx(nid)];
2748 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2750 static int adc_idx[8] = {
2751 0, 1, 2, 8, 4, 3, 6, 7
2754 case AD1988_PIN_CD_NID:
2757 return adc_idx[ad1988_pin_idx(nid)];
2761 /* fill in the dac_nids table from the parsed pin configuration */
2762 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2763 const struct auto_pin_cfg *cfg)
2765 struct ad198x_spec *spec = codec->spec;
2768 spec->multiout.dac_nids = spec->private_dac_nids;
2770 /* check the pins hardwired to audio widget */
2771 for (i = 0; i < cfg->line_outs; i++) {
2772 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2773 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2775 spec->multiout.num_dacs = cfg->line_outs;
2779 /* add playback controls from the parsed DAC table */
2780 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2781 const struct auto_pin_cfg *cfg)
2784 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2788 for (i = 0; i < cfg->line_outs; i++) {
2789 hda_nid_t dac = spec->multiout.dac_nids[i];
2792 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2795 err = add_control(spec, AD_CTL_WIDGET_VOL,
2796 "Center Playback Volume",
2797 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2800 err = add_control(spec, AD_CTL_WIDGET_VOL,
2801 "LFE Playback Volume",
2802 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2805 err = add_control(spec, AD_CTL_BIND_MUTE,
2806 "Center Playback Switch",
2807 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2810 err = add_control(spec, AD_CTL_BIND_MUTE,
2811 "LFE Playback Switch",
2812 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2816 sprintf(name, "%s Playback Volume", chname[i]);
2817 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2818 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2821 sprintf(name, "%s Playback Switch", chname[i]);
2822 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2823 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2831 /* add playback controls for speaker and HP outputs */
2832 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2835 struct ad198x_spec *spec = codec->spec;
2843 idx = ad1988_pin_idx(pin);
2844 nid = ad1988_idx_to_dac(codec, idx);
2845 /* check whether the corresponding DAC was already taken */
2846 for (i = 0; i < spec->autocfg.line_outs; i++) {
2847 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2848 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2852 if (i >= spec->autocfg.line_outs) {
2853 /* specify the DAC as the extra output */
2854 if (!spec->multiout.hp_nid)
2855 spec->multiout.hp_nid = nid;
2857 spec->multiout.extra_out_nid[0] = nid;
2858 /* control HP volume/switch on the output mixer amp */
2859 sprintf(name, "%s Playback Volume", pfx);
2860 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2861 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2865 nid = ad1988_mixer_nids[idx];
2866 sprintf(name, "%s Playback Switch", pfx);
2867 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2868 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2873 /* create input playback/capture controls for the given pin */
2874 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2875 const char *ctlname, int boost)
2880 sprintf(name, "%s Playback Volume", ctlname);
2881 idx = ad1988_pin_to_loopback_idx(pin);
2882 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2883 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2885 sprintf(name, "%s Playback Switch", ctlname);
2886 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2887 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2891 idx = ad1988_pin_idx(pin);
2892 bnid = ad1988_boost_nids[idx];
2894 sprintf(name, "%s Boost", ctlname);
2895 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2896 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2903 /* create playback/capture controls for input pins */
2904 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2905 const struct auto_pin_cfg *cfg)
2907 struct hda_input_mux *imux = &spec->private_imux;
2910 for (i = 0; i < AUTO_PIN_LAST; i++) {
2911 err = new_analog_input(spec, cfg->input_pins[i],
2912 auto_pin_cfg_labels[i],
2913 i <= AUTO_PIN_FRONT_MIC);
2916 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2917 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2920 imux->items[imux->num_items].label = "Mix";
2921 imux->items[imux->num_items].index = 9;
2924 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2925 "Analog Mix Playback Volume",
2926 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2928 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2929 "Analog Mix Playback Switch",
2930 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2936 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2937 hda_nid_t nid, int pin_type,
2941 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2942 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2944 case 0x11: /* port-A - DAC 04 */
2945 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2947 case 0x14: /* port-B - DAC 06 */
2948 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2950 case 0x15: /* port-C - DAC 05 */
2951 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2953 case 0x17: /* port-E - DAC 0a */
2954 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2956 case 0x13: /* mono - DAC 04 */
2957 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2962 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2964 struct ad198x_spec *spec = codec->spec;
2967 for (i = 0; i < spec->autocfg.line_outs; i++) {
2968 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2969 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2973 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2975 struct ad198x_spec *spec = codec->spec;
2978 pin = spec->autocfg.speaker_pins[0];
2979 if (pin) /* connect to front */
2980 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2981 pin = spec->autocfg.hp_pins[0];
2982 if (pin) /* connect to front */
2983 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2986 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2988 struct ad198x_spec *spec = codec->spec;
2991 for (i = 0; i < AUTO_PIN_LAST; i++) {
2992 hda_nid_t nid = spec->autocfg.input_pins[i];
2996 case 0x15: /* port-C */
2997 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2999 case 0x17: /* port-E */
3000 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3003 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3004 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3005 if (nid != AD1988_PIN_CD_NID)
3006 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3008 idx = ad1988_pin_idx(nid);
3009 if (ad1988_boost_nids[idx])
3010 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3011 AC_VERB_SET_AMP_GAIN_MUTE,
3016 /* parse the BIOS configuration and set up the alc_spec */
3017 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3018 static int ad1988_parse_auto_config(struct hda_codec *codec)
3020 struct ad198x_spec *spec = codec->spec;
3023 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3025 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3027 if (! spec->autocfg.line_outs)
3028 return 0; /* can't find valid BIOS pin config */
3029 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3030 (err = ad1988_auto_create_extra_out(codec,
3031 spec->autocfg.speaker_pins[0],
3033 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3034 "Headphone")) < 0 ||
3035 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3038 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3040 if (spec->autocfg.dig_outs)
3041 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3042 if (spec->autocfg.dig_in_pin)
3043 spec->dig_in_nid = AD1988_SPDIF_IN;
3045 if (spec->kctls.list)
3046 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3048 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3050 spec->input_mux = &spec->private_imux;
3055 /* init callback for auto-configuration model -- overriding the default init */
3056 static int ad1988_auto_init(struct hda_codec *codec)
3059 ad1988_auto_init_multi_out(codec);
3060 ad1988_auto_init_extra_out(codec);
3061 ad1988_auto_init_analog_input(codec);
3069 static const char *ad1988_models[AD1988_MODEL_LAST] = {
3070 [AD1988_6STACK] = "6stack",
3071 [AD1988_6STACK_DIG] = "6stack-dig",
3072 [AD1988_3STACK] = "3stack",
3073 [AD1988_3STACK_DIG] = "3stack-dig",
3074 [AD1988_LAPTOP] = "laptop",
3075 [AD1988_LAPTOP_DIG] = "laptop-dig",
3076 [AD1988_AUTO] = "auto",
3079 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
3080 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3081 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3082 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3083 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3087 static int patch_ad1988(struct hda_codec *codec)
3089 struct ad198x_spec *spec;
3090 int err, board_config;
3092 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3099 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3101 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3102 ad1988_models, ad1988_cfg_tbl);
3103 if (board_config < 0) {
3104 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3106 board_config = AD1988_AUTO;
3109 if (board_config == AD1988_AUTO) {
3110 /* automatic parse from the BIOS config */
3111 err = ad1988_parse_auto_config(codec);
3116 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3117 board_config = AD1988_6STACK;
3121 err = snd_hda_attach_beep_device(codec, 0x10);
3126 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3128 switch (board_config) {
3130 case AD1988_6STACK_DIG:
3131 spec->multiout.max_channels = 8;
3132 spec->multiout.num_dacs = 4;
3134 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3136 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3137 spec->input_mux = &ad1988_6stack_capture_source;
3138 spec->num_mixers = 2;
3140 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3142 spec->mixers[0] = ad1988_6stack_mixers1;
3143 spec->mixers[1] = ad1988_6stack_mixers2;
3144 spec->num_init_verbs = 1;
3145 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3146 if (board_config == AD1988_6STACK_DIG) {
3147 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3148 spec->dig_in_nid = AD1988_SPDIF_IN;
3152 case AD1988_3STACK_DIG:
3153 spec->multiout.max_channels = 6;
3154 spec->multiout.num_dacs = 3;
3156 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3158 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3159 spec->input_mux = &ad1988_6stack_capture_source;
3160 spec->channel_mode = ad1988_3stack_modes;
3161 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3162 spec->num_mixers = 2;
3164 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3166 spec->mixers[0] = ad1988_3stack_mixers1;
3167 spec->mixers[1] = ad1988_3stack_mixers2;
3168 spec->num_init_verbs = 1;
3169 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3170 if (board_config == AD1988_3STACK_DIG)
3171 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3174 case AD1988_LAPTOP_DIG:
3175 spec->multiout.max_channels = 2;
3176 spec->multiout.num_dacs = 1;
3177 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3178 spec->input_mux = &ad1988_laptop_capture_source;
3179 spec->num_mixers = 1;
3180 spec->mixers[0] = ad1988_laptop_mixers;
3181 spec->inv_eapd = 1; /* inverted EAPD */
3182 spec->num_init_verbs = 1;
3183 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3184 if (board_config == AD1988_LAPTOP_DIG)
3185 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3189 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3190 spec->adc_nids = ad1988_adc_nids;
3191 spec->capsrc_nids = ad1988_capsrc_nids;
3192 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3193 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3194 if (spec->multiout.dig_out_nid) {
3195 if (codec->vendor_id >= 0x11d4989a) {
3196 spec->mixers[spec->num_mixers++] =
3197 ad1989_spdif_out_mixers;
3198 spec->init_verbs[spec->num_init_verbs++] =
3199 ad1989_spdif_init_verbs;
3200 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3202 spec->mixers[spec->num_mixers++] =
3203 ad1988_spdif_out_mixers;
3204 spec->init_verbs[spec->num_init_verbs++] =
3205 ad1988_spdif_init_verbs;
3208 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3209 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3210 spec->init_verbs[spec->num_init_verbs++] =
3211 ad1988_spdif_in_init_verbs;
3214 codec->patch_ops = ad198x_patch_ops;
3215 switch (board_config) {
3217 codec->patch_ops.init = ad1988_auto_init;
3220 case AD1988_LAPTOP_DIG:
3221 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3224 #ifdef CONFIG_SND_HDA_POWER_SAVE
3225 spec->loopback.amplist = ad1988_loopbacks;
3227 spec->vmaster_nid = 0x04;
3229 codec->no_trigger_sense = 1;
3238 * port-B - front line/mic-in
3239 * port-E - aux in/out
3240 * port-F - aux in/out
3241 * port-C - rear line/mic-in
3242 * port-D - rear line/hp-out
3243 * port-A - front line/hp-out
3245 * AD1984 = AD1884 + two digital mic-ins
3248 * For simplicity, we share the single DAC for both HP and line-outs
3249 * right now. The inidividual playbacks could be easily implemented,
3250 * but no build-up framework is given, so far.
3253 static hda_nid_t ad1884_dac_nids[1] = {
3257 static hda_nid_t ad1884_adc_nids[2] = {
3261 static hda_nid_t ad1884_capsrc_nids[2] = {
3265 #define AD1884_SPDIF_OUT 0x02
3267 static struct hda_input_mux ad1884_capture_source = {
3270 { "Front Mic", 0x0 },
3277 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3278 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3279 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3280 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3281 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3282 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3283 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3284 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3285 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3286 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3287 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3288 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3289 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3290 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3291 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3292 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3293 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3294 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3295 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3297 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3298 /* The multiple "Capture Source" controls confuse alsamixer
3299 * So call somewhat different..
3301 /* .name = "Capture Source", */
3302 .name = "Input Source",
3304 .info = ad198x_mux_enum_info,
3305 .get = ad198x_mux_enum_get,
3306 .put = ad198x_mux_enum_put,
3308 /* SPDIF controls */
3309 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3311 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3312 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3313 /* identical with ad1983 */
3314 .info = ad1983_spdif_route_info,
3315 .get = ad1983_spdif_route_get,
3316 .put = ad1983_spdif_route_put,
3321 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3322 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3323 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3324 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3326 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3332 * initialization verbs
3334 static struct hda_verb ad1884_init_verbs[] = {
3335 /* DACs; mute as default */
3336 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3337 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3338 /* Port-A (HP) mixer */
3339 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3340 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3342 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3343 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3344 /* HP selector - select DAC2 */
3345 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3346 /* Port-D (Line-out) mixer */
3347 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3348 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3350 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3351 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3352 /* Mono-out mixer */
3353 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3354 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3356 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3357 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3359 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3360 /* Port-B (front mic) pin */
3361 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3362 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3363 /* Port-C (rear mic) pin */
3364 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3365 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3366 /* Analog mixer; mute as default */
3367 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3368 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3369 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3370 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3371 /* Analog Mix output amp */
3372 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3373 /* SPDIF output selector */
3374 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3375 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3379 #ifdef CONFIG_SND_HDA_POWER_SAVE
3380 static struct hda_amp_list ad1884_loopbacks[] = {
3381 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3382 { 0x20, HDA_INPUT, 1 }, /* Mic */
3383 { 0x20, HDA_INPUT, 2 }, /* CD */
3384 { 0x20, HDA_INPUT, 4 }, /* Docking */
3389 static const char *ad1884_slave_vols[] = {
3390 "PCM Playback Volume",
3391 "Mic Playback Volume",
3392 "Mono Playback Volume",
3393 "Front Mic Playback Volume",
3394 "Mic Playback Volume",
3395 "CD Playback Volume",
3396 "Internal Mic Playback Volume",
3397 "Docking Mic Playback Volume",
3398 /* "Beep Playback Volume", */
3399 "IEC958 Playback Volume",
3403 static int patch_ad1884(struct hda_codec *codec)
3405 struct ad198x_spec *spec;
3408 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3414 err = snd_hda_attach_beep_device(codec, 0x10);
3419 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3421 spec->multiout.max_channels = 2;
3422 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3423 spec->multiout.dac_nids = ad1884_dac_nids;
3424 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3425 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3426 spec->adc_nids = ad1884_adc_nids;
3427 spec->capsrc_nids = ad1884_capsrc_nids;
3428 spec->input_mux = &ad1884_capture_source;
3429 spec->num_mixers = 1;
3430 spec->mixers[0] = ad1884_base_mixers;
3431 spec->num_init_verbs = 1;
3432 spec->init_verbs[0] = ad1884_init_verbs;
3433 spec->spdif_route = 0;
3434 #ifdef CONFIG_SND_HDA_POWER_SAVE
3435 spec->loopback.amplist = ad1884_loopbacks;
3437 spec->vmaster_nid = 0x04;
3438 /* we need to cover all playback volumes */
3439 spec->slave_vols = ad1884_slave_vols;
3441 codec->patch_ops = ad198x_patch_ops;
3443 codec->no_trigger_sense = 1;
3449 * Lenovo Thinkpad T61/X61
3451 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3455 { "Internal Mic", 0x1 },
3457 { "Docking-Station", 0x4 },
3463 * Dell Precision T3400
3465 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3468 { "Front Mic", 0x0 },
3475 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3476 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3477 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3478 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3479 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3480 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3481 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3482 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3483 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3484 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3485 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3486 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3487 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3488 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3489 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3490 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3491 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3492 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3494 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3495 /* The multiple "Capture Source" controls confuse alsamixer
3496 * So call somewhat different..
3498 /* .name = "Capture Source", */
3499 .name = "Input Source",
3501 .info = ad198x_mux_enum_info,
3502 .get = ad198x_mux_enum_get,
3503 .put = ad198x_mux_enum_put,
3505 /* SPDIF controls */
3506 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3509 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3510 /* identical with ad1983 */
3511 .info = ad1983_spdif_route_info,
3512 .get = ad1983_spdif_route_get,
3513 .put = ad1983_spdif_route_put,
3518 /* additional verbs */
3519 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3520 /* Port-E (docking station mic) pin */
3521 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3522 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3523 /* docking mic boost */
3524 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3525 /* Analog mixer - docking mic; mute as default */
3526 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3527 /* enable EAPD bit */
3528 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3533 * Dell Precision T3400
3535 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3536 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3537 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3538 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3539 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3540 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3541 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3542 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3543 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3544 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3545 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3546 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3547 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3548 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3549 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3550 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3553 /* The multiple "Capture Source" controls confuse alsamixer
3554 * So call somewhat different..
3556 /* .name = "Capture Source", */
3557 .name = "Input Source",
3559 .info = ad198x_mux_enum_info,
3560 .get = ad198x_mux_enum_get,
3561 .put = ad198x_mux_enum_put,
3566 /* Digial MIC ADC NID 0x05 + 0x06 */
3567 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3568 struct hda_codec *codec,
3569 unsigned int stream_tag,
3570 unsigned int format,
3571 struct snd_pcm_substream *substream)
3573 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3574 stream_tag, 0, format);
3578 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3579 struct hda_codec *codec,
3580 struct snd_pcm_substream *substream)
3582 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3586 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3592 .prepare = ad1984_pcm_dmic_prepare,
3593 .cleanup = ad1984_pcm_dmic_cleanup
3597 static int ad1984_build_pcms(struct hda_codec *codec)
3599 struct ad198x_spec *spec = codec->spec;
3600 struct hda_pcm *info;
3603 err = ad198x_build_pcms(codec);
3607 info = spec->pcm_rec + codec->num_pcms;
3609 info->name = "AD1984 Digital Mic";
3610 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3618 AD1984_DELL_DESKTOP,
3622 static const char *ad1984_models[AD1984_MODELS] = {
3623 [AD1984_BASIC] = "basic",
3624 [AD1984_THINKPAD] = "thinkpad",
3625 [AD1984_DELL_DESKTOP] = "dell_desktop",
3628 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3629 /* Lenovo Thinkpad T61/X61 */
3630 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3631 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3635 static int patch_ad1984(struct hda_codec *codec)
3637 struct ad198x_spec *spec;
3638 int board_config, err;
3640 err = patch_ad1884(codec);
3644 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3645 ad1984_models, ad1984_cfg_tbl);
3646 switch (board_config) {
3648 /* additional digital mics */
3649 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3650 codec->patch_ops.build_pcms = ad1984_build_pcms;
3652 case AD1984_THINKPAD:
3653 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3654 spec->input_mux = &ad1984_thinkpad_capture_source;
3655 spec->mixers[0] = ad1984_thinkpad_mixers;
3656 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3658 case AD1984_DELL_DESKTOP:
3659 spec->multiout.dig_out_nid = 0;
3660 spec->input_mux = &ad1984_dell_desktop_capture_source;
3661 spec->mixers[0] = ad1984_dell_desktop_mixers;
3669 * AD1883 / AD1884A / AD1984A / AD1984B
3671 * port-B (0x14) - front mic-in
3672 * port-E (0x1c) - rear mic-in
3673 * port-F (0x16) - CD / ext out
3674 * port-C (0x15) - rear line-in
3675 * port-D (0x12) - rear line-out
3676 * port-A (0x11) - front hp-out
3678 * AD1984A = AD1884A + digital-mic
3679 * AD1883 = equivalent with AD1984A
3680 * AD1984B = AD1984A + extra SPDIF-out
3683 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3686 static hda_nid_t ad1884a_dac_nids[1] = {
3690 #define ad1884a_adc_nids ad1884_adc_nids
3691 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3693 #define AD1884A_SPDIF_OUT 0x02
3695 static struct hda_input_mux ad1884a_capture_source = {
3698 { "Front Mic", 0x0 },
3706 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3707 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3708 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3709 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3710 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3711 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3712 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3713 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3714 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3715 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3716 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3717 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3718 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3719 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3720 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3721 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3722 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3723 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3724 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3725 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3726 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3727 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3728 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3729 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3731 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3732 /* The multiple "Capture Source" controls confuse alsamixer
3733 * So call somewhat different..
3735 /* .name = "Capture Source", */
3736 .name = "Input Source",
3738 .info = ad198x_mux_enum_info,
3739 .get = ad198x_mux_enum_get,
3740 .put = ad198x_mux_enum_put,
3742 /* SPDIF controls */
3743 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3745 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3746 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3747 /* identical with ad1983 */
3748 .info = ad1983_spdif_route_info,
3749 .get = ad1983_spdif_route_get,
3750 .put = ad1983_spdif_route_put,
3756 * initialization verbs
3758 static struct hda_verb ad1884a_init_verbs[] = {
3759 /* DACs; unmute as default */
3760 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3761 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3762 /* Port-A (HP) mixer - route only from analog mixer */
3763 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3764 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3766 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3767 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3768 /* Port-D (Line-out) mixer - route only from analog mixer */
3769 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3770 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3772 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3773 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3774 /* Mono-out mixer - route only from analog mixer */
3775 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3776 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3778 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3779 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3780 /* Port-B (front mic) pin */
3781 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3782 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3783 /* Port-C (rear line-in) pin */
3784 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3785 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3786 /* Port-E (rear mic) pin */
3787 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3788 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3789 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3790 /* Port-F (CD) pin */
3791 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3792 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3793 /* Analog mixer; mute as default */
3794 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3795 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3796 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3797 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3798 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3799 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3800 /* Analog Mix output amp */
3801 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3802 /* capture sources */
3803 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3804 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3805 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3806 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3807 /* SPDIF output amp */
3808 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3812 #ifdef CONFIG_SND_HDA_POWER_SAVE
3813 static struct hda_amp_list ad1884a_loopbacks[] = {
3814 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3815 { 0x20, HDA_INPUT, 1 }, /* Mic */
3816 { 0x20, HDA_INPUT, 2 }, /* CD */
3817 { 0x20, HDA_INPUT, 4 }, /* Docking */
3825 * Port A: Headphone jack
3827 * Port C: Internal MIC
3828 * Port D: Dock Line Out (if enabled)
3829 * Port E: Dock Line In (if enabled)
3830 * Port F: Internal speakers
3833 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3834 struct snd_ctl_elem_value *ucontrol)
3836 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3837 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3838 int mute = (!ucontrol->value.integer.value[0] &&
3839 !ucontrol->value.integer.value[1]);
3840 /* toggle GPIO1 according to the mute state */
3841 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3846 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3847 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3850 .name = "Master Playback Switch",
3851 .subdevice = HDA_SUBDEV_AMP_FLAG,
3852 .info = snd_hda_mixer_amp_switch_info,
3853 .get = snd_hda_mixer_amp_switch_get,
3854 .put = ad1884a_mobile_master_sw_put,
3855 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3857 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3858 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3859 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3860 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3861 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3862 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3863 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3864 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3865 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3866 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3867 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3868 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3869 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3870 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3874 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3875 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3876 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3879 .name = "Master Playback Switch",
3880 .subdevice = HDA_SUBDEV_AMP_FLAG,
3881 .info = snd_hda_mixer_amp_switch_info,
3882 .get = snd_hda_mixer_amp_switch_get,
3883 .put = ad1884a_mobile_master_sw_put,
3884 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3886 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3887 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3888 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3889 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3890 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3891 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3895 /* mute internal speaker if HP is plugged */
3896 static void ad1884a_hp_automute(struct hda_codec *codec)
3898 unsigned int present;
3900 present = snd_hda_jack_detect(codec, 0x11);
3901 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3902 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3903 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3904 present ? 0x00 : 0x02);
3907 /* switch to external mic if plugged */
3908 static void ad1884a_hp_automic(struct hda_codec *codec)
3910 unsigned int present;
3912 present = snd_hda_jack_detect(codec, 0x14);
3913 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3917 #define AD1884A_HP_EVENT 0x37
3918 #define AD1884A_MIC_EVENT 0x36
3920 /* unsolicited event for HP jack sensing */
3921 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3923 switch (res >> 26) {
3924 case AD1884A_HP_EVENT:
3925 ad1884a_hp_automute(codec);
3927 case AD1884A_MIC_EVENT:
3928 ad1884a_hp_automic(codec);
3933 /* initialize jack-sensing, too */
3934 static int ad1884a_hp_init(struct hda_codec *codec)
3937 ad1884a_hp_automute(codec);
3938 ad1884a_hp_automic(codec);
3942 /* mute internal speaker if HP or docking HP is plugged */
3943 static void ad1884a_laptop_automute(struct hda_codec *codec)
3945 unsigned int present;
3947 present = snd_hda_jack_detect(codec, 0x11);
3949 present = snd_hda_jack_detect(codec, 0x12);
3950 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3951 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3952 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3953 present ? 0x00 : 0x02);
3956 /* switch to external mic if plugged */
3957 static void ad1884a_laptop_automic(struct hda_codec *codec)
3961 if (snd_hda_jack_detect(codec, 0x14))
3963 else if (snd_hda_jack_detect(codec, 0x1c))
3967 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3970 /* unsolicited event for HP jack sensing */
3971 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3974 switch (res >> 26) {
3975 case AD1884A_HP_EVENT:
3976 ad1884a_laptop_automute(codec);
3978 case AD1884A_MIC_EVENT:
3979 ad1884a_laptop_automic(codec);
3984 /* initialize jack-sensing, too */
3985 static int ad1884a_laptop_init(struct hda_codec *codec)
3988 ad1884a_laptop_automute(codec);
3989 ad1884a_laptop_automic(codec);
3993 /* additional verbs for laptop model */
3994 static struct hda_verb ad1884a_laptop_verbs[] = {
3995 /* Port-A (HP) pin - always unmuted */
3996 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3997 /* Port-F (int speaker) mixer - route only from analog mixer */
3998 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3999 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4000 /* Port-F (int speaker) pin */
4001 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4002 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4003 /* required for compaq 6530s/6531s speaker output */
4004 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4005 /* Port-C pin - internal mic-in */
4006 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4007 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4008 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4009 /* Port-D (docking line-out) pin - default unmuted */
4010 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4012 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4013 /* unsolicited event for pin-sense */
4014 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4015 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4016 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4017 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4018 /* allow to touch GPIO1 (for mute control) */
4019 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4020 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4021 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4025 static struct hda_verb ad1884a_mobile_verbs[] = {
4026 /* DACs; unmute as default */
4027 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4028 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4029 /* Port-A (HP) mixer - route only from analog mixer */
4030 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4031 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4033 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4034 /* Port-A (HP) pin - always unmuted */
4035 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4036 /* Port-B (mic jack) pin */
4037 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4038 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4039 /* Port-C (int mic) pin */
4040 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4041 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4042 /* Port-F (int speaker) mixer - route only from analog mixer */
4043 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4044 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4046 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4047 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4048 /* Analog mixer; mute as default */
4049 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4050 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4051 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4052 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4053 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4054 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4055 /* Analog Mix output amp */
4056 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4057 /* capture sources */
4058 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4059 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4060 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4061 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4062 /* unsolicited event for pin-sense */
4063 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4064 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4065 /* allow to touch GPIO1 (for mute control) */
4066 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4067 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4068 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4077 * 0x17 - built-in mic
4080 static struct hda_verb ad1984a_thinkpad_verbs[] = {
4082 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4084 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4086 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4087 /* unsolicited event for pin-sense */
4088 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4089 /* internal mic - dmic */
4090 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4091 /* set magic COEFs for dmic */
4092 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4093 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4097 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4098 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4099 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4100 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4101 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4102 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4103 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4104 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4105 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4106 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4107 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4109 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4110 .name = "Capture Source",
4111 .info = ad198x_mux_enum_info,
4112 .get = ad198x_mux_enum_get,
4113 .put = ad198x_mux_enum_put,
4118 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4122 { "Internal Mic", 0x5 },
4127 /* mute internal speaker if HP is plugged */
4128 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4130 unsigned int present;
4132 present = snd_hda_jack_detect(codec, 0x11);
4133 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4134 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4137 /* unsolicited event for HP jack sensing */
4138 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4141 if ((res >> 26) != AD1884A_HP_EVENT)
4143 ad1984a_thinkpad_automute(codec);
4146 /* initialize jack-sensing, too */
4147 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4150 ad1984a_thinkpad_automute(codec);
4156 * port-A (0x11) - front hp-out
4157 * port-B (0x14) - unused
4158 * port-C (0x15) - unused
4159 * port-D (0x12) - rear line out
4160 * port-E (0x1c) - front mic-in
4161 * port-F (0x16) - Internal speakers
4162 * digital-mic (0x17) - Internal mic
4165 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4166 /* DACs; unmute as default */
4167 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4168 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4169 /* Port-A (HP) mixer - route only from analog mixer */
4170 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4171 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4173 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4174 /* Port-A (HP) pin - always unmuted */
4175 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4176 /* Port-E (int speaker) mixer - route only from analog mixer */
4177 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4179 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4180 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4181 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4182 /* Port-F (int speaker) mixer - route only from analog mixer */
4183 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4184 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4186 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4187 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4188 /* Analog mixer; mute as default */
4189 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4190 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4191 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4192 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4193 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4194 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4195 /* Analog Mix output amp */
4196 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4197 /* capture sources */
4198 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4199 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4200 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4201 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4202 /* unsolicited event for pin-sense */
4203 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4204 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4205 /* allow to touch GPIO1 (for mute control) */
4206 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4207 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4208 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4209 /* internal mic - dmic */
4210 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4211 /* set magic COEFs for dmic */
4212 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4213 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4217 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4218 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4219 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4222 .subdevice = HDA_SUBDEV_AMP_FLAG,
4223 .name = "Master Playback Switch",
4224 .info = snd_hda_mixer_amp_switch_info,
4225 .get = snd_hda_mixer_amp_switch_get,
4226 .put = ad1884a_mobile_master_sw_put,
4227 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4229 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4230 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4231 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4232 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4233 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4234 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4238 /* switch to external mic if plugged */
4239 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4241 if (snd_hda_jack_detect(codec, 0x1c))
4242 snd_hda_codec_write(codec, 0x0c, 0,
4243 AC_VERB_SET_CONNECT_SEL, 0x4);
4245 snd_hda_codec_write(codec, 0x0c, 0,
4246 AC_VERB_SET_CONNECT_SEL, 0x5);
4250 /* unsolicited event for HP jack sensing */
4251 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4254 switch (res >> 26) {
4255 case AD1884A_HP_EVENT:
4256 ad1884a_hp_automute(codec);
4258 case AD1884A_MIC_EVENT:
4259 ad1984a_touchsmart_automic(codec);
4264 /* initialize jack-sensing, too */
4265 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4268 ad1884a_hp_automute(codec);
4269 ad1984a_touchsmart_automic(codec);
4286 static const char *ad1884a_models[AD1884A_MODELS] = {
4287 [AD1884A_DESKTOP] = "desktop",
4288 [AD1884A_LAPTOP] = "laptop",
4289 [AD1884A_MOBILE] = "mobile",
4290 [AD1884A_THINKPAD] = "thinkpad",
4291 [AD1984A_TOUCHSMART] = "touchsmart",
4294 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4295 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4296 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4297 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4298 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4299 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4300 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4301 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4302 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4303 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4304 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4308 static int patch_ad1884a(struct hda_codec *codec)
4310 struct ad198x_spec *spec;
4311 int err, board_config;
4313 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4319 err = snd_hda_attach_beep_device(codec, 0x10);
4324 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4326 spec->multiout.max_channels = 2;
4327 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4328 spec->multiout.dac_nids = ad1884a_dac_nids;
4329 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4330 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4331 spec->adc_nids = ad1884a_adc_nids;
4332 spec->capsrc_nids = ad1884a_capsrc_nids;
4333 spec->input_mux = &ad1884a_capture_source;
4334 spec->num_mixers = 1;
4335 spec->mixers[0] = ad1884a_base_mixers;
4336 spec->num_init_verbs = 1;
4337 spec->init_verbs[0] = ad1884a_init_verbs;
4338 spec->spdif_route = 0;
4339 #ifdef CONFIG_SND_HDA_POWER_SAVE
4340 spec->loopback.amplist = ad1884a_loopbacks;
4342 codec->patch_ops = ad198x_patch_ops;
4344 /* override some parameters */
4345 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4348 switch (board_config) {
4349 case AD1884A_LAPTOP:
4350 spec->mixers[0] = ad1884a_laptop_mixers;
4351 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4352 spec->multiout.dig_out_nid = 0;
4353 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4354 codec->patch_ops.init = ad1884a_laptop_init;
4355 /* set the upper-limit for mixer amp to 0dB for avoiding the
4356 * possible damage by overloading
4358 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4359 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4360 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4361 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4362 (1 << AC_AMPCAP_MUTE_SHIFT));
4364 case AD1884A_MOBILE:
4365 spec->mixers[0] = ad1884a_mobile_mixers;
4366 spec->init_verbs[0] = ad1884a_mobile_verbs;
4367 spec->multiout.dig_out_nid = 0;
4368 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4369 codec->patch_ops.init = ad1884a_hp_init;
4370 /* set the upper-limit for mixer amp to 0dB for avoiding the
4371 * possible damage by overloading
4373 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4374 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4375 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4376 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4377 (1 << AC_AMPCAP_MUTE_SHIFT));
4379 case AD1884A_THINKPAD:
4380 spec->mixers[0] = ad1984a_thinkpad_mixers;
4381 spec->init_verbs[spec->num_init_verbs++] =
4382 ad1984a_thinkpad_verbs;
4383 spec->multiout.dig_out_nid = 0;
4384 spec->input_mux = &ad1984a_thinkpad_capture_source;
4385 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4386 codec->patch_ops.init = ad1984a_thinkpad_init;
4388 case AD1984A_TOUCHSMART:
4389 spec->mixers[0] = ad1984a_touchsmart_mixers;
4390 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4391 spec->multiout.dig_out_nid = 0;
4392 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4393 codec->patch_ops.init = ad1984a_touchsmart_init;
4394 /* set the upper-limit for mixer amp to 0dB for avoiding the
4395 * possible damage by overloading
4397 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4398 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4399 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4400 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4401 (1 << AC_AMPCAP_MUTE_SHIFT));
4405 codec->no_trigger_sense = 1;
4414 * port-A - front hp-out
4415 * port-B - front mic-in
4416 * port-C - rear line-in, shared surr-out (3stack)
4417 * port-D - rear line-out
4418 * port-E - rear mic-in, shared clfe-out (3stack)
4419 * port-F - rear surr-out (6stack)
4420 * port-G - rear clfe-out (6stack)
4423 static hda_nid_t ad1882_dac_nids[3] = {
4427 static hda_nid_t ad1882_adc_nids[2] = {
4431 static hda_nid_t ad1882_capsrc_nids[2] = {
4435 #define AD1882_SPDIF_OUT 0x02
4437 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4438 static struct hda_input_mux ad1882_capture_source = {
4441 { "Front Mic", 0x1 },
4449 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4450 static struct hda_input_mux ad1882a_capture_source = {
4453 { "Front Mic", 0x1 },
4456 { "Digital Mic", 0x06 },
4461 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4462 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4463 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4464 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4465 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4466 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4467 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4468 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4469 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4471 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4472 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4473 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4474 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4475 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4476 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4477 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4479 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4480 /* The multiple "Capture Source" controls confuse alsamixer
4481 * So call somewhat different..
4483 /* .name = "Capture Source", */
4484 .name = "Input Source",
4486 .info = ad198x_mux_enum_info,
4487 .get = ad198x_mux_enum_get,
4488 .put = ad198x_mux_enum_put,
4490 /* SPDIF controls */
4491 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4494 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4495 /* identical with ad1983 */
4496 .info = ad1983_spdif_route_info,
4497 .get = ad1983_spdif_route_get,
4498 .put = ad1983_spdif_route_put,
4503 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4504 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4505 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4506 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4507 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4508 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4509 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4510 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4511 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4515 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4516 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4517 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4518 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4519 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4520 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4521 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4522 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4523 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4524 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4528 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4529 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4530 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4531 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4534 .name = "Channel Mode",
4535 .info = ad198x_ch_mode_info,
4536 .get = ad198x_ch_mode_get,
4537 .put = ad198x_ch_mode_put,
4542 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4543 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4544 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4545 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4549 static struct hda_verb ad1882_ch2_init[] = {
4550 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4551 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4552 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4553 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4554 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4555 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4559 static struct hda_verb ad1882_ch4_init[] = {
4560 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4561 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4562 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4563 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4564 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4565 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4569 static struct hda_verb ad1882_ch6_init[] = {
4570 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4571 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4572 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4573 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4574 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4575 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4579 static struct hda_channel_mode ad1882_modes[3] = {
4580 { 2, ad1882_ch2_init },
4581 { 4, ad1882_ch4_init },
4582 { 6, ad1882_ch6_init },
4586 * initialization verbs
4588 static struct hda_verb ad1882_init_verbs[] = {
4589 /* DACs; mute as default */
4590 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4591 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4592 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4593 /* Port-A (HP) mixer */
4594 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4595 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4597 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4598 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4599 /* HP selector - select DAC2 */
4600 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4601 /* Port-D (Line-out) mixer */
4602 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4603 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4605 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4606 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4607 /* Mono-out mixer */
4608 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4609 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4611 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4612 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4613 /* Port-B (front mic) pin */
4614 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4615 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4616 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4617 /* Port-C (line-in) pin */
4618 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4619 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4620 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4621 /* Port-C mixer - mute as input */
4622 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4623 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4624 /* Port-E (mic-in) pin */
4625 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4626 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4627 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4628 /* Port-E mixer - mute as input */
4629 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4630 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4631 /* Port-F (surround) */
4632 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4633 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4635 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4636 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4637 /* Analog mixer; mute as default */
4638 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4639 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4640 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4641 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4642 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4643 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4644 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4645 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4646 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4647 /* Analog Mix output amp */
4648 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4649 /* SPDIF output selector */
4650 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4651 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4652 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4656 #ifdef CONFIG_SND_HDA_POWER_SAVE
4657 static struct hda_amp_list ad1882_loopbacks[] = {
4658 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4659 { 0x20, HDA_INPUT, 1 }, /* Mic */
4660 { 0x20, HDA_INPUT, 4 }, /* Line */
4661 { 0x20, HDA_INPUT, 6 }, /* CD */
4673 static const char *ad1882_models[AD1986A_MODELS] = {
4674 [AD1882_3STACK] = "3stack",
4675 [AD1882_6STACK] = "6stack",
4679 static int patch_ad1882(struct hda_codec *codec)
4681 struct ad198x_spec *spec;
4682 int err, board_config;
4684 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4690 err = snd_hda_attach_beep_device(codec, 0x10);
4695 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4697 spec->multiout.max_channels = 6;
4698 spec->multiout.num_dacs = 3;
4699 spec->multiout.dac_nids = ad1882_dac_nids;
4700 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4701 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4702 spec->adc_nids = ad1882_adc_nids;
4703 spec->capsrc_nids = ad1882_capsrc_nids;
4704 if (codec->vendor_id == 0x11d41882)
4705 spec->input_mux = &ad1882_capture_source;
4707 spec->input_mux = &ad1882a_capture_source;
4708 spec->num_mixers = 2;
4709 spec->mixers[0] = ad1882_base_mixers;
4710 if (codec->vendor_id == 0x11d41882)
4711 spec->mixers[1] = ad1882_loopback_mixers;
4713 spec->mixers[1] = ad1882a_loopback_mixers;
4714 spec->num_init_verbs = 1;
4715 spec->init_verbs[0] = ad1882_init_verbs;
4716 spec->spdif_route = 0;
4717 #ifdef CONFIG_SND_HDA_POWER_SAVE
4718 spec->loopback.amplist = ad1882_loopbacks;
4720 spec->vmaster_nid = 0x04;
4722 codec->patch_ops = ad198x_patch_ops;
4724 /* override some parameters */
4725 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4726 ad1882_models, NULL);
4727 switch (board_config) {
4730 spec->num_mixers = 3;
4731 spec->mixers[2] = ad1882_3stack_mixers;
4732 spec->channel_mode = ad1882_modes;
4733 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4734 spec->need_dac_fix = 1;
4735 spec->multiout.max_channels = 2;
4736 spec->multiout.num_dacs = 1;
4739 spec->num_mixers = 3;
4740 spec->mixers[2] = ad1882_6stack_mixers;
4744 codec->no_trigger_sense = 1;
4753 static struct hda_codec_preset snd_hda_preset_analog[] = {
4754 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4755 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4756 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4757 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4758 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4759 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4760 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4761 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4762 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4763 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4764 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4765 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4766 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4767 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4768 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4772 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4774 MODULE_LICENSE("GPL");
4775 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4777 static struct hda_codec_preset_list analog_list = {
4778 .preset = snd_hda_preset_analog,
4779 .owner = THIS_MODULE,
4782 static int __init patch_analog_init(void)
4784 return snd_hda_add_codec_preset(&analog_list);
4787 static void __exit patch_analog_exit(void)
4789 snd_hda_delete_codec_preset(&analog_list);
4792 module_init(patch_analog_init)
4793 module_exit(patch_analog_exit)