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);
523 static int ad198x_resume(struct hda_codec *codec)
526 snd_hda_codec_resume_amp(codec);
527 snd_hda_codec_resume_cache(codec);
532 static struct hda_codec_ops ad198x_patch_ops = {
533 .build_controls = ad198x_build_controls,
534 .build_pcms = ad198x_build_pcms,
537 #ifdef CONFIG_SND_HDA_POWER_SAVE
538 .check_power_status = ad198x_check_power_status,
540 #ifdef SND_HDA_NEEDS_RESUME
541 .suspend = ad198x_suspend,
542 .resume = ad198x_resume,
544 .reboot_notify = ad198x_shutup,
550 * the private value = nid
552 #define ad198x_eapd_info snd_ctl_boolean_mono_info
554 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
555 struct snd_ctl_elem_value *ucontrol)
557 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
558 struct ad198x_spec *spec = codec->spec;
560 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
562 ucontrol->value.integer.value[0] = spec->cur_eapd;
566 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
567 struct snd_ctl_elem_value *ucontrol)
569 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
570 struct ad198x_spec *spec = codec->spec;
571 hda_nid_t nid = kcontrol->private_value & 0xff;
573 eapd = !!ucontrol->value.integer.value[0];
576 if (eapd == spec->cur_eapd)
578 spec->cur_eapd = eapd;
579 snd_hda_codec_write_cache(codec, nid,
580 0, AC_VERB_SET_EAPD_BTLENABLE,
585 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
586 struct snd_ctl_elem_info *uinfo);
587 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
588 struct snd_ctl_elem_value *ucontrol);
589 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
590 struct snd_ctl_elem_value *ucontrol);
597 #define AD1986A_SPDIF_OUT 0x02
598 #define AD1986A_FRONT_DAC 0x03
599 #define AD1986A_SURR_DAC 0x04
600 #define AD1986A_CLFE_DAC 0x05
601 #define AD1986A_ADC 0x06
603 static hda_nid_t ad1986a_dac_nids[3] = {
604 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
606 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
607 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
609 static struct hda_input_mux ad1986a_capture_source = {
623 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
624 .ops = &snd_hda_bind_vol,
626 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
627 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
628 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
633 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
634 .ops = &snd_hda_bind_sw,
636 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
637 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
638 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
646 static struct snd_kcontrol_new ad1986a_mixers[] = {
648 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
650 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
651 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
652 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
653 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
654 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
655 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
656 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
657 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
658 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
659 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
660 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
661 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
662 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
665 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
666 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
667 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
668 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
669 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
670 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
671 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
672 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
673 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
674 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
676 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
677 .name = "Capture Source",
678 .info = ad198x_mux_enum_info,
679 .get = ad198x_mux_enum_get,
680 .put = ad198x_mux_enum_put,
682 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
686 /* additional mixers for 3stack mode */
687 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
689 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
690 .name = "Channel Mode",
691 .info = ad198x_ch_mode_info,
692 .get = ad198x_ch_mode_get,
693 .put = ad198x_ch_mode_put,
698 /* laptop model - 2ch only */
699 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
701 /* master controls both pins 0x1a and 0x1b */
702 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
703 .ops = &snd_hda_bind_vol,
705 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
706 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
711 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
712 .ops = &snd_hda_bind_sw,
714 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
715 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
720 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
721 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
722 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
723 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
724 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
725 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
726 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
727 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
728 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
729 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
730 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
731 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
732 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
733 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
735 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
736 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
737 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
738 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
741 .name = "Capture Source",
742 .info = ad198x_mux_enum_info,
743 .get = ad198x_mux_enum_get,
744 .put = ad198x_mux_enum_put,
749 /* laptop-eapd model - 2ch only */
751 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
755 { "Internal Mic", 0x4 },
760 static struct hda_input_mux ad1986a_automic_capture_source = {
768 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
769 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
770 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
774 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
775 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
776 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
777 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
778 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
779 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
780 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
781 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
783 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
784 .name = "Capture Source",
785 .info = ad198x_mux_enum_info,
786 .get = ad198x_mux_enum_get,
787 .put = ad198x_mux_enum_put,
790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
791 .name = "External Amplifier",
792 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
793 .info = ad198x_eapd_info,
794 .get = ad198x_eapd_get,
795 .put = ad198x_eapd_put,
796 .private_value = 0x1b, /* port-D */
801 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
802 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
803 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
807 /* re-connect the mic boost input according to the jack sensing */
808 static void ad1986a_automic(struct hda_codec *codec)
810 unsigned int present;
811 present = snd_hda_jack_detect(codec, 0x1f);
812 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
813 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
817 #define AD1986A_MIC_EVENT 0x36
819 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
822 if ((res >> 26) != AD1986A_MIC_EVENT)
824 ad1986a_automic(codec);
827 static int ad1986a_automic_init(struct hda_codec *codec)
830 ad1986a_automic(codec);
834 /* laptop-automute - 2ch only */
836 static void ad1986a_update_hp(struct hda_codec *codec)
838 struct ad198x_spec *spec = codec->spec;
841 if (spec->jack_present)
842 mute = HDA_AMP_MUTE; /* mute internal speaker */
844 /* unmute internal speaker if necessary */
845 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
846 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
850 static void ad1986a_hp_automute(struct hda_codec *codec)
852 struct ad198x_spec *spec = codec->spec;
854 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
855 if (spec->inv_jack_detect)
856 spec->jack_present = !spec->jack_present;
857 ad1986a_update_hp(codec);
860 #define AD1986A_HP_EVENT 0x37
862 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
864 if ((res >> 26) != AD1986A_HP_EVENT)
866 ad1986a_hp_automute(codec);
869 static int ad1986a_hp_init(struct hda_codec *codec)
872 ad1986a_hp_automute(codec);
876 /* bind hp and internal speaker mute (with plug check) */
877 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
878 struct snd_ctl_elem_value *ucontrol)
880 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
881 long *valp = ucontrol->value.integer.value;
884 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
886 valp[0] ? 0 : HDA_AMP_MUTE);
887 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
889 valp[1] ? 0 : HDA_AMP_MUTE);
891 ad1986a_update_hp(codec);
895 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
896 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
898 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
899 .name = "Master Playback Switch",
900 .subdevice = HDA_SUBDEV_AMP_FLAG,
901 .info = snd_hda_mixer_amp_switch_info,
902 .get = snd_hda_mixer_amp_switch_get,
903 .put = ad1986a_hp_master_sw_put,
904 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
911 * initialization verbs
913 static struct hda_verb ad1986a_init_verbs[] = {
914 /* Front, Surround, CLFE DAC; mute as default */
915 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
916 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
917 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
919 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
920 /* HP, Line-Out, Surround, CLFE selectors */
921 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
922 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
923 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
924 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
926 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
927 /* Mic selector: Mic 1/2 pin */
928 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
929 /* Line-in selector: Line-in */
930 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
932 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
933 /* Record selector: mic */
934 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
935 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
936 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
937 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
938 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
939 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
940 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
942 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
943 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
944 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
945 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
946 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
947 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
948 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
950 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
951 /* Front, Surround, CLFE Pins */
952 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
953 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
954 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
956 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
958 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
959 /* Line, Aux, CD, Beep-In Pin */
960 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
961 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
962 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
963 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
964 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
968 static struct hda_verb ad1986a_ch2_init[] = {
969 /* Surround out -> Line In */
970 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
971 /* Line-in selectors */
972 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
974 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
975 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
976 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
980 static struct hda_verb ad1986a_ch4_init[] = {
981 /* Surround out -> Surround */
982 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
983 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
985 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
986 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
990 static struct hda_verb ad1986a_ch6_init[] = {
991 /* Surround out -> Surround out */
992 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
993 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
995 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
996 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1000 static struct hda_channel_mode ad1986a_modes[3] = {
1001 { 2, ad1986a_ch2_init },
1002 { 4, ad1986a_ch4_init },
1003 { 6, ad1986a_ch6_init },
1006 /* eapd initialization */
1007 static struct hda_verb ad1986a_eapd_init_verbs[] = {
1008 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1012 static struct hda_verb ad1986a_automic_verbs[] = {
1013 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1014 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1015 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1016 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1017 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1021 /* Ultra initialization */
1022 static struct hda_verb ad1986a_ultra_init[] = {
1023 /* eapd initialization */
1024 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1025 /* CLFE -> Mic in */
1026 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1027 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1028 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1032 /* pin sensing on HP jack */
1033 static struct hda_verb ad1986a_hp_init_verbs[] = {
1034 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1038 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1041 switch (res >> 26) {
1042 case AD1986A_HP_EVENT:
1043 ad1986a_hp_automute(codec);
1045 case AD1986A_MIC_EVENT:
1046 ad1986a_automic(codec);
1051 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1054 ad1986a_hp_automute(codec);
1055 ad1986a_automic(codec);
1065 AD1986A_LAPTOP_EAPD,
1066 AD1986A_LAPTOP_AUTOMUTE,
1069 AD1986A_SAMSUNG_P50,
1073 static const char *ad1986a_models[AD1986A_MODELS] = {
1074 [AD1986A_6STACK] = "6stack",
1075 [AD1986A_3STACK] = "3stack",
1076 [AD1986A_LAPTOP] = "laptop",
1077 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1078 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1079 [AD1986A_ULTRA] = "ultra",
1080 [AD1986A_SAMSUNG] = "samsung",
1081 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1084 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1085 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1086 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1087 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1088 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1089 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1090 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1091 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1092 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1093 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1094 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1095 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1096 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1097 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1098 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1099 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1100 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1101 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
1102 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1103 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1104 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1105 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1106 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1107 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1108 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1109 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1110 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1111 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1115 #ifdef CONFIG_SND_HDA_POWER_SAVE
1116 static struct hda_amp_list ad1986a_loopbacks[] = {
1117 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1118 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1119 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1120 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1121 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1126 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1128 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1129 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1132 static int patch_ad1986a(struct hda_codec *codec)
1134 struct ad198x_spec *spec;
1135 int err, board_config;
1137 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1143 err = snd_hda_attach_beep_device(codec, 0x19);
1148 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1150 spec->multiout.max_channels = 6;
1151 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1152 spec->multiout.dac_nids = ad1986a_dac_nids;
1153 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1154 spec->num_adc_nids = 1;
1155 spec->adc_nids = ad1986a_adc_nids;
1156 spec->capsrc_nids = ad1986a_capsrc_nids;
1157 spec->input_mux = &ad1986a_capture_source;
1158 spec->num_mixers = 1;
1159 spec->mixers[0] = ad1986a_mixers;
1160 spec->num_init_verbs = 1;
1161 spec->init_verbs[0] = ad1986a_init_verbs;
1162 #ifdef CONFIG_SND_HDA_POWER_SAVE
1163 spec->loopback.amplist = ad1986a_loopbacks;
1165 spec->vmaster_nid = 0x1b;
1166 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1168 codec->patch_ops = ad198x_patch_ops;
1170 /* override some parameters */
1171 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1174 switch (board_config) {
1175 case AD1986A_3STACK:
1176 spec->num_mixers = 2;
1177 spec->mixers[1] = ad1986a_3st_mixers;
1178 spec->num_init_verbs = 2;
1179 spec->init_verbs[1] = ad1986a_ch2_init;
1180 spec->channel_mode = ad1986a_modes;
1181 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1182 spec->need_dac_fix = 1;
1183 spec->multiout.max_channels = 2;
1184 spec->multiout.num_dacs = 1;
1186 case AD1986A_LAPTOP:
1187 spec->mixers[0] = ad1986a_laptop_mixers;
1188 spec->multiout.max_channels = 2;
1189 spec->multiout.num_dacs = 1;
1190 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1192 case AD1986A_LAPTOP_EAPD:
1193 spec->num_mixers = 3;
1194 spec->mixers[0] = ad1986a_laptop_master_mixers;
1195 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1196 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1197 spec->num_init_verbs = 2;
1198 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1199 spec->multiout.max_channels = 2;
1200 spec->multiout.num_dacs = 1;
1201 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1202 if (!is_jack_available(codec, 0x25))
1203 spec->multiout.dig_out_nid = 0;
1204 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1206 case AD1986A_SAMSUNG:
1207 spec->num_mixers = 2;
1208 spec->mixers[0] = ad1986a_laptop_master_mixers;
1209 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1210 spec->num_init_verbs = 3;
1211 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1212 spec->init_verbs[2] = ad1986a_automic_verbs;
1213 spec->multiout.max_channels = 2;
1214 spec->multiout.num_dacs = 1;
1215 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1216 if (!is_jack_available(codec, 0x25))
1217 spec->multiout.dig_out_nid = 0;
1218 spec->input_mux = &ad1986a_automic_capture_source;
1219 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1220 codec->patch_ops.init = ad1986a_automic_init;
1222 case AD1986A_SAMSUNG_P50:
1223 spec->num_mixers = 2;
1224 spec->mixers[0] = ad1986a_automute_master_mixers;
1225 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1226 spec->num_init_verbs = 4;
1227 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1228 spec->init_verbs[2] = ad1986a_automic_verbs;
1229 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1230 spec->multiout.max_channels = 2;
1231 spec->multiout.num_dacs = 1;
1232 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1233 if (!is_jack_available(codec, 0x25))
1234 spec->multiout.dig_out_nid = 0;
1235 spec->input_mux = &ad1986a_automic_capture_source;
1236 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1237 codec->patch_ops.init = ad1986a_samsung_p50_init;
1239 case AD1986A_LAPTOP_AUTOMUTE:
1240 spec->num_mixers = 3;
1241 spec->mixers[0] = ad1986a_automute_master_mixers;
1242 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1243 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1244 spec->num_init_verbs = 3;
1245 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1246 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1247 spec->multiout.max_channels = 2;
1248 spec->multiout.num_dacs = 1;
1249 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1250 if (!is_jack_available(codec, 0x25))
1251 spec->multiout.dig_out_nid = 0;
1252 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1253 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1254 codec->patch_ops.init = ad1986a_hp_init;
1255 /* Lenovo N100 seems to report the reversed bit
1256 * for HP jack-sensing
1258 spec->inv_jack_detect = 1;
1261 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1262 spec->num_init_verbs = 2;
1263 spec->init_verbs[1] = ad1986a_ultra_init;
1264 spec->multiout.max_channels = 2;
1265 spec->multiout.num_dacs = 1;
1266 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1267 spec->multiout.dig_out_nid = 0;
1271 /* AD1986A has a hardware problem that it can't share a stream
1272 * with multiple output pins. The copy of front to surrounds
1273 * causes noisy or silent outputs at a certain timing, e.g.
1274 * changing the volume.
1275 * So, let's disable the shared stream.
1277 spec->multiout.no_share_stream = 1;
1286 #define AD1983_SPDIF_OUT 0x02
1287 #define AD1983_DAC 0x03
1288 #define AD1983_ADC 0x04
1290 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1291 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1292 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1294 static struct hda_input_mux ad1983_capture_source = {
1300 { "Mix Mono", 0x3 },
1305 * SPDIF playback route
1307 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1309 static char *texts[] = { "PCM", "ADC" };
1311 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1313 uinfo->value.enumerated.items = 2;
1314 if (uinfo->value.enumerated.item > 1)
1315 uinfo->value.enumerated.item = 1;
1316 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1320 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1322 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1323 struct ad198x_spec *spec = codec->spec;
1325 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1329 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1331 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1332 struct ad198x_spec *spec = codec->spec;
1334 if (ucontrol->value.enumerated.item[0] > 1)
1336 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1337 spec->spdif_route = ucontrol->value.enumerated.item[0];
1338 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1339 AC_VERB_SET_CONNECT_SEL,
1346 static struct snd_kcontrol_new ad1983_mixers[] = {
1347 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1348 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1349 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1350 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1351 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1352 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1353 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1354 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1355 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1356 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1357 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1358 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1359 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1360 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1361 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1363 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1364 .name = "Capture Source",
1365 .info = ad198x_mux_enum_info,
1366 .get = ad198x_mux_enum_get,
1367 .put = ad198x_mux_enum_put,
1370 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1371 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1372 .info = ad1983_spdif_route_info,
1373 .get = ad1983_spdif_route_get,
1374 .put = ad1983_spdif_route_put,
1379 static struct hda_verb ad1983_init_verbs[] = {
1380 /* Front, HP, Mono; mute as default */
1381 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1382 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1383 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1384 /* Beep, PCM, Mic, Line-In: mute */
1385 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1386 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1387 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1388 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1389 /* Front, HP selectors; from Mix */
1390 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1391 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1392 /* Mono selector; from Mix */
1393 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1394 /* Mic selector; Mic */
1395 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1396 /* Line-in selector: Line-in */
1397 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1398 /* Mic boost: 0dB */
1399 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1400 /* Record selector: mic */
1401 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1402 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1403 /* SPDIF route: PCM */
1404 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1406 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1408 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1410 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1412 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1414 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1418 #ifdef CONFIG_SND_HDA_POWER_SAVE
1419 static struct hda_amp_list ad1983_loopbacks[] = {
1420 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1421 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1426 static int patch_ad1983(struct hda_codec *codec)
1428 struct ad198x_spec *spec;
1431 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1437 err = snd_hda_attach_beep_device(codec, 0x10);
1442 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1444 spec->multiout.max_channels = 2;
1445 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1446 spec->multiout.dac_nids = ad1983_dac_nids;
1447 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1448 spec->num_adc_nids = 1;
1449 spec->adc_nids = ad1983_adc_nids;
1450 spec->capsrc_nids = ad1983_capsrc_nids;
1451 spec->input_mux = &ad1983_capture_source;
1452 spec->num_mixers = 1;
1453 spec->mixers[0] = ad1983_mixers;
1454 spec->num_init_verbs = 1;
1455 spec->init_verbs[0] = ad1983_init_verbs;
1456 spec->spdif_route = 0;
1457 #ifdef CONFIG_SND_HDA_POWER_SAVE
1458 spec->loopback.amplist = ad1983_loopbacks;
1460 spec->vmaster_nid = 0x05;
1462 codec->patch_ops = ad198x_patch_ops;
1469 * AD1981 HD specific
1472 #define AD1981_SPDIF_OUT 0x02
1473 #define AD1981_DAC 0x03
1474 #define AD1981_ADC 0x04
1476 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1477 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1478 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1480 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1481 static struct hda_input_mux ad1981_capture_source = {
1484 { "Front Mic", 0x0 },
1487 { "Mix Mono", 0x3 },
1494 static struct snd_kcontrol_new ad1981_mixers[] = {
1495 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1496 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1497 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1498 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1499 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1500 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1507 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1509 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1512 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1513 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1514 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1515 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1516 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1518 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1519 .name = "Capture Source",
1520 .info = ad198x_mux_enum_info,
1521 .get = ad198x_mux_enum_get,
1522 .put = ad198x_mux_enum_put,
1524 /* identical with AD1983 */
1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1528 .info = ad1983_spdif_route_info,
1529 .get = ad1983_spdif_route_get,
1530 .put = ad1983_spdif_route_put,
1535 static struct hda_verb ad1981_init_verbs[] = {
1536 /* Front, HP, Mono; mute as default */
1537 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1538 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1539 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1540 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1541 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1542 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1543 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1544 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1545 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1546 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1547 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1548 /* Front, HP selectors; from Mix */
1549 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1550 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1551 /* Mono selector; from Mix */
1552 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1553 /* Mic Mixer; select Front Mic */
1554 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1555 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1556 /* Mic boost: 0dB */
1557 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1558 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1559 /* Record selector: Front mic */
1560 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1561 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1562 /* SPDIF route: PCM */
1563 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1565 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1567 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1569 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1570 /* Front & Rear Mic Pins */
1571 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1572 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1574 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1576 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1577 /* Line-Out as Input: disabled */
1578 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1582 #ifdef CONFIG_SND_HDA_POWER_SAVE
1583 static struct hda_amp_list ad1981_loopbacks[] = {
1584 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1585 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1586 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1587 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1588 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1594 * Patch for HP nx6320
1596 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1597 * speaker output enabled _and_ mute-LED off.
1600 #define AD1981_HP_EVENT 0x37
1601 #define AD1981_MIC_EVENT 0x38
1603 static struct hda_verb ad1981_hp_init_verbs[] = {
1604 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1605 /* pin sensing on HP and Mic jacks */
1606 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1607 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1611 /* turn on/off EAPD (+ mute HP) as a master switch */
1612 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1613 struct snd_ctl_elem_value *ucontrol)
1615 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1616 struct ad198x_spec *spec = codec->spec;
1618 if (! ad198x_eapd_put(kcontrol, ucontrol))
1620 /* change speaker pin appropriately */
1621 snd_hda_codec_write(codec, 0x05, 0,
1622 AC_VERB_SET_PIN_WIDGET_CONTROL,
1623 spec->cur_eapd ? PIN_OUT : 0);
1624 /* toggle HP mute appropriately */
1625 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1627 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1631 /* bind volumes of both NID 0x05 and 0x06 */
1632 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1633 .ops = &snd_hda_bind_vol,
1635 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1636 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1641 /* mute internal speaker if HP is plugged */
1642 static void ad1981_hp_automute(struct hda_codec *codec)
1644 unsigned int present;
1646 present = snd_hda_jack_detect(codec, 0x06);
1647 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1648 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1651 /* toggle input of built-in and mic jack appropriately */
1652 static void ad1981_hp_automic(struct hda_codec *codec)
1654 static struct hda_verb mic_jack_on[] = {
1655 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1656 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1659 static struct hda_verb mic_jack_off[] = {
1660 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1661 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1664 unsigned int present;
1666 present = snd_hda_jack_detect(codec, 0x08);
1668 snd_hda_sequence_write(codec, mic_jack_on);
1670 snd_hda_sequence_write(codec, mic_jack_off);
1673 /* unsolicited event for HP jack sensing */
1674 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1679 case AD1981_HP_EVENT:
1680 ad1981_hp_automute(codec);
1682 case AD1981_MIC_EVENT:
1683 ad1981_hp_automic(codec);
1688 static struct hda_input_mux ad1981_hp_capture_source = {
1692 { "Docking-Station", 0x1 },
1697 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1698 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1700 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1701 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1702 .name = "Master Playback Switch",
1703 .info = ad198x_eapd_info,
1704 .get = ad198x_eapd_get,
1705 .put = ad1981_hp_master_sw_put,
1706 .private_value = 0x05,
1708 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1709 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1711 /* FIXME: analog mic/line loopback doesn't work with my tests...
1712 * (although recording is OK)
1714 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1715 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1716 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1717 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1718 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1719 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1720 /* FIXME: does this laptop have analog CD connection? */
1721 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1722 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1724 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1725 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1726 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1727 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730 .name = "Capture Source",
1731 .info = ad198x_mux_enum_info,
1732 .get = ad198x_mux_enum_get,
1733 .put = ad198x_mux_enum_put,
1738 /* initialize jack-sensing, too */
1739 static int ad1981_hp_init(struct hda_codec *codec)
1742 ad1981_hp_automute(codec);
1743 ad1981_hp_automic(codec);
1747 /* configuration for Toshiba Laptops */
1748 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1749 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1750 /* pin sensing on HP and Mic jacks */
1751 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1752 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1756 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1757 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1758 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1762 /* configuration for Lenovo Thinkpad T60 */
1763 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1764 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1765 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1766 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1767 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1768 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1769 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1770 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1771 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1772 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1773 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1774 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1777 .name = "Capture Source",
1778 .info = ad198x_mux_enum_info,
1779 .get = ad198x_mux_enum_get,
1780 .put = ad198x_mux_enum_put,
1782 /* identical with AD1983 */
1784 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1785 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1786 .info = ad1983_spdif_route_info,
1787 .get = ad1983_spdif_route_get,
1788 .put = ad1983_spdif_route_put,
1793 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1811 static const char *ad1981_models[AD1981_MODELS] = {
1813 [AD1981_THINKPAD] = "thinkpad",
1814 [AD1981_BASIC] = "basic",
1815 [AD1981_TOSHIBA] = "toshiba"
1818 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1819 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1820 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1822 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1823 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1824 /* Lenovo Thinkpad T60/X60/Z6xx */
1825 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1826 /* HP nx6320 (reversed SSID, H/W bug) */
1827 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1831 static int patch_ad1981(struct hda_codec *codec)
1833 struct ad198x_spec *spec;
1834 int err, board_config;
1836 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1842 err = snd_hda_attach_beep_device(codec, 0x10);
1847 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1849 spec->multiout.max_channels = 2;
1850 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1851 spec->multiout.dac_nids = ad1981_dac_nids;
1852 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1853 spec->num_adc_nids = 1;
1854 spec->adc_nids = ad1981_adc_nids;
1855 spec->capsrc_nids = ad1981_capsrc_nids;
1856 spec->input_mux = &ad1981_capture_source;
1857 spec->num_mixers = 1;
1858 spec->mixers[0] = ad1981_mixers;
1859 spec->num_init_verbs = 1;
1860 spec->init_verbs[0] = ad1981_init_verbs;
1861 spec->spdif_route = 0;
1862 #ifdef CONFIG_SND_HDA_POWER_SAVE
1863 spec->loopback.amplist = ad1981_loopbacks;
1865 spec->vmaster_nid = 0x05;
1867 codec->patch_ops = ad198x_patch_ops;
1869 /* override some parameters */
1870 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1873 switch (board_config) {
1875 spec->mixers[0] = ad1981_hp_mixers;
1876 spec->num_init_verbs = 2;
1877 spec->init_verbs[1] = ad1981_hp_init_verbs;
1878 spec->multiout.dig_out_nid = 0;
1879 spec->input_mux = &ad1981_hp_capture_source;
1881 codec->patch_ops.init = ad1981_hp_init;
1882 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1883 /* set the upper-limit for mixer amp to 0dB for avoiding the
1884 * possible damage by overloading
1886 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1887 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1888 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1889 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1890 (1 << AC_AMPCAP_MUTE_SHIFT));
1892 case AD1981_THINKPAD:
1893 spec->mixers[0] = ad1981_thinkpad_mixers;
1894 spec->input_mux = &ad1981_thinkpad_capture_source;
1896 case AD1981_TOSHIBA:
1897 spec->mixers[0] = ad1981_hp_mixers;
1898 spec->mixers[1] = ad1981_toshiba_mixers;
1899 spec->num_init_verbs = 2;
1900 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1901 spec->multiout.dig_out_nid = 0;
1902 spec->input_mux = &ad1981_hp_capture_source;
1903 codec->patch_ops.init = ad1981_hp_init;
1904 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1914 * Output pins and routes
1916 * Pin Mix Sel DAC (*)
1917 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1918 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1919 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1920 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1921 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1922 * port-F 0x16 (mute) <- 0x2a <- 06
1923 * port-G 0x24 (mute) <- 0x27 <- 05
1924 * port-H 0x25 (mute) <- 0x28 <- 0a
1925 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1927 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1928 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1930 * Input pins and routes
1932 * pin boost mix input # / adc input #
1933 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1934 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1935 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1936 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1937 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1938 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1939 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1940 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1944 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1945 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1947 * Inputs of Analog Mix (0x20)
1948 * 0:Port-B (front mic)
1949 * 1:Port-C/G/H (line-in)
1951 * 3:Port-D (line-in/2)
1952 * 4:Port-E/G/H (mic-in)
1953 * 5:Port-F (mic2-in)
1959 * 1:Port-B (front mic-in)
1960 * 2:Port-C (line-in)
1961 * 3:Port-F (mic2-in)
1966 * 8:Port-D (line-in/2)
1969 * Proposed pin assignments by the datasheet
1972 * Port-A front headphone
1982 * Port-A front headphone
1984 * C rear line-in/surround
1986 * E rear mic-in/CLFE
1992 * D internal speaker (with EAPD)
1993 * E/F quad mic array
2009 /* reivision id to check workarounds */
2010 #define AD1988A_REV2 0x100200
2012 #define is_rev2(codec) \
2013 ((codec)->vendor_id == 0x11d41988 && \
2014 (codec)->revision_id == AD1988A_REV2)
2020 static hda_nid_t ad1988_6stack_dac_nids[4] = {
2021 0x04, 0x06, 0x05, 0x0a
2024 static hda_nid_t ad1988_3stack_dac_nids[3] = {
2028 /* for AD1988A revision-2, DAC2-4 are swapped */
2029 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2030 0x04, 0x05, 0x0a, 0x06
2033 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2037 static hda_nid_t ad1988_adc_nids[3] = {
2041 static hda_nid_t ad1988_capsrc_nids[3] = {
2045 #define AD1988_SPDIF_OUT 0x02
2046 #define AD1988_SPDIF_OUT_HDMI 0x0b
2047 #define AD1988_SPDIF_IN 0x07
2049 static hda_nid_t ad1989b_slave_dig_outs[] = {
2050 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2053 static struct hda_input_mux ad1988_6stack_capture_source = {
2056 { "Front Mic", 0x1 }, /* port-B */
2057 { "Line", 0x2 }, /* port-C */
2058 { "Mic", 0x4 }, /* port-E */
2064 static struct hda_input_mux ad1988_laptop_capture_source = {
2067 { "Mic/Line", 0x1 }, /* port-B */
2075 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2076 struct snd_ctl_elem_info *uinfo)
2078 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2079 struct ad198x_spec *spec = codec->spec;
2080 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2081 spec->num_channel_mode);
2084 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2085 struct snd_ctl_elem_value *ucontrol)
2087 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2088 struct ad198x_spec *spec = codec->spec;
2089 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2090 spec->num_channel_mode, spec->multiout.max_channels);
2093 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2094 struct snd_ctl_elem_value *ucontrol)
2096 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2097 struct ad198x_spec *spec = codec->spec;
2098 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2099 spec->num_channel_mode,
2100 &spec->multiout.max_channels);
2101 if (err >= 0 && spec->need_dac_fix)
2102 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2107 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2108 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2109 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2110 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2111 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2112 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2116 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2117 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2118 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2119 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2120 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2121 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2125 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2126 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2127 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2128 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2129 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2130 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2131 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2132 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2134 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2135 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2136 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2137 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2138 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2139 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2140 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2141 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2143 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2144 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2146 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2147 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2153 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2154 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2155 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2156 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2157 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2161 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2162 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2163 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2164 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2165 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2169 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2170 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2171 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2172 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2173 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2174 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2175 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2177 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2178 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2179 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2180 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2181 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2182 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2183 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2184 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2186 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2187 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2189 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2190 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2192 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2193 .name = "Channel Mode",
2194 .info = ad198x_ch_mode_info,
2195 .get = ad198x_ch_mode_get,
2196 .put = ad198x_ch_mode_put,
2203 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2204 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2205 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2206 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2208 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2209 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2210 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2211 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2212 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2213 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2215 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2216 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2218 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2222 .name = "External Amplifier",
2223 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2224 .info = ad198x_eapd_info,
2225 .get = ad198x_eapd_get,
2226 .put = ad198x_eapd_put,
2227 .private_value = 0x12, /* port-D */
2234 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2235 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2236 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2237 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2238 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2239 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2240 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2242 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2243 /* The multiple "Capture Source" controls confuse alsamixer
2244 * So call somewhat different..
2246 /* .name = "Capture Source", */
2247 .name = "Input Source",
2249 .info = ad198x_mux_enum_info,
2250 .get = ad198x_mux_enum_get,
2251 .put = ad198x_mux_enum_put,
2256 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2257 struct snd_ctl_elem_info *uinfo)
2259 static char *texts[] = {
2260 "PCM", "ADC1", "ADC2", "ADC3"
2262 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2264 uinfo->value.enumerated.items = 4;
2265 if (uinfo->value.enumerated.item >= 4)
2266 uinfo->value.enumerated.item = 3;
2267 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2271 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2272 struct snd_ctl_elem_value *ucontrol)
2274 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2277 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2280 ucontrol->value.enumerated.item[0] = 0;
2282 sel = snd_hda_codec_read(codec, 0x0b, 0,
2283 AC_VERB_GET_CONNECT_SEL, 0);
2288 ucontrol->value.enumerated.item[0] = sel;
2293 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2294 struct snd_ctl_elem_value *ucontrol)
2296 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2297 unsigned int val, sel;
2300 val = ucontrol->value.enumerated.item[0];
2304 sel = snd_hda_codec_read(codec, 0x1d, 0,
2305 AC_VERB_GET_AMP_GAIN_MUTE,
2307 change = sel & 0x80;
2309 snd_hda_codec_write_cache(codec, 0x1d, 0,
2310 AC_VERB_SET_AMP_GAIN_MUTE,
2312 snd_hda_codec_write_cache(codec, 0x1d, 0,
2313 AC_VERB_SET_AMP_GAIN_MUTE,
2317 sel = snd_hda_codec_read(codec, 0x1d, 0,
2318 AC_VERB_GET_AMP_GAIN_MUTE,
2319 AC_AMP_GET_INPUT | 0x01);
2320 change = sel & 0x80;
2322 snd_hda_codec_write_cache(codec, 0x1d, 0,
2323 AC_VERB_SET_AMP_GAIN_MUTE,
2325 snd_hda_codec_write_cache(codec, 0x1d, 0,
2326 AC_VERB_SET_AMP_GAIN_MUTE,
2329 sel = snd_hda_codec_read(codec, 0x0b, 0,
2330 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2331 change |= sel != val;
2333 snd_hda_codec_write_cache(codec, 0x0b, 0,
2334 AC_VERB_SET_CONNECT_SEL,
2340 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2341 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2343 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2344 .name = "IEC958 Playback Source",
2345 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2346 .info = ad1988_spdif_playback_source_info,
2347 .get = ad1988_spdif_playback_source_get,
2348 .put = ad1988_spdif_playback_source_put,
2353 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2354 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2358 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2359 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2360 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2365 * initialization verbs
2369 * for 6-stack (+dig)
2371 static struct hda_verb ad1988_6stack_init_verbs[] = {
2372 /* Front, Surround, CLFE, side DAC; unmute as default */
2373 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2374 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2375 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2376 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2377 /* Port-A front headphon path */
2378 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2379 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2380 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2381 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2382 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2383 /* Port-D line-out path */
2384 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2385 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2386 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2387 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2388 /* Port-F surround path */
2389 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2390 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2391 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2392 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2393 /* Port-G CLFE path */
2394 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2395 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2396 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2397 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2398 /* Port-H side path */
2399 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2400 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2401 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2402 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2404 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2405 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2406 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2407 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2408 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2409 /* Port-B front mic-in path */
2410 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2411 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2412 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2413 /* Port-C line-in path */
2414 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2415 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2416 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2417 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2418 /* Port-E mic-in path */
2419 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2420 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2421 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2422 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2423 /* Analog CD Input */
2424 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2425 /* Analog Mix output amp */
2426 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2431 static struct hda_verb ad1988_capture_init_verbs[] = {
2432 /* mute analog mix */
2433 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2434 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2435 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2436 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2437 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2438 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2441 /* select ADCs - front-mic */
2442 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2443 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2444 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2449 static struct hda_verb ad1988_spdif_init_verbs[] = {
2451 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2452 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2453 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2454 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2456 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2461 static struct hda_verb ad1988_spdif_in_init_verbs[] = {
2462 /* unmute SPDIF input pin */
2463 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2467 /* AD1989 has no ADC -> SPDIF route */
2468 static struct hda_verb ad1989_spdif_init_verbs[] = {
2469 /* SPDIF-1 out pin */
2470 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2471 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2472 /* SPDIF-2/HDMI out pin */
2473 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2474 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2479 * verbs for 3stack (+dig)
2481 static struct hda_verb ad1988_3stack_ch2_init[] = {
2482 /* set port-C to line-in */
2483 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2484 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2485 /* set port-E to mic-in */
2486 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2487 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2491 static struct hda_verb ad1988_3stack_ch6_init[] = {
2492 /* set port-C to surround out */
2493 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2494 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2495 /* set port-E to CLFE out */
2496 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2497 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2501 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2502 { 2, ad1988_3stack_ch2_init },
2503 { 6, ad1988_3stack_ch6_init },
2506 static struct hda_verb ad1988_3stack_init_verbs[] = {
2507 /* Front, Surround, CLFE, side DAC; unmute as default */
2508 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2509 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2510 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2511 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2512 /* Port-A front headphon path */
2513 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2514 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2515 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2516 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2517 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2518 /* Port-D line-out path */
2519 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2520 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2521 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2522 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2524 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2525 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2526 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2527 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2528 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2529 /* Port-B front mic-in path */
2530 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2531 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2532 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2533 /* Port-C line-in/surround path - 6ch mode as default */
2534 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2535 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2536 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2537 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2538 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2539 /* Port-E mic-in/CLFE path - 6ch mode as default */
2540 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2541 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2542 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2543 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2544 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2545 /* mute analog mix */
2546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2549 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2550 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2551 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2552 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2553 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2554 /* select ADCs - front-mic */
2555 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2556 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2557 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2558 /* Analog Mix output amp */
2559 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2564 * verbs for laptop mode (+dig)
2566 static struct hda_verb ad1988_laptop_hp_on[] = {
2567 /* unmute port-A and mute port-D */
2568 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2569 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2572 static struct hda_verb ad1988_laptop_hp_off[] = {
2573 /* mute port-A and unmute port-D */
2574 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2575 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2579 #define AD1988_HP_EVENT 0x01
2581 static struct hda_verb ad1988_laptop_init_verbs[] = {
2582 /* Front, Surround, CLFE, side DAC; unmute as default */
2583 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2584 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2585 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2586 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2587 /* Port-A front headphon path */
2588 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2589 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2590 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2591 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2592 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2593 /* unsolicited event for pin-sense */
2594 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2595 /* Port-D line-out path + EAPD */
2596 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2597 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2598 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2599 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2600 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2602 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2603 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2604 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2605 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2606 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2607 /* Port-B mic-in path */
2608 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2609 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2610 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2611 /* Port-C docking station - try to output */
2612 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2613 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2614 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2615 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2616 /* mute analog mix */
2617 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2618 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2619 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2620 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2621 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2622 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2623 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2624 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2625 /* select ADCs - mic */
2626 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2627 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2628 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2629 /* Analog Mix output amp */
2630 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2634 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2636 if ((res >> 26) != AD1988_HP_EVENT)
2638 if (snd_hda_jack_detect(codec, 0x11))
2639 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2641 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2644 #ifdef CONFIG_SND_HDA_POWER_SAVE
2645 static struct hda_amp_list ad1988_loopbacks[] = {
2646 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2647 { 0x20, HDA_INPUT, 1 }, /* Line */
2648 { 0x20, HDA_INPUT, 4 }, /* Mic */
2649 { 0x20, HDA_INPUT, 6 }, /* CD */
2655 * Automatic parse of I/O pins from the BIOS configuration
2663 static struct snd_kcontrol_new ad1988_control_templates[] = {
2664 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2665 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2666 HDA_BIND_MUTE(NULL, 0, 0, 0),
2669 /* add dynamic controls */
2670 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2673 struct snd_kcontrol_new *knew;
2675 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2676 knew = snd_array_new(&spec->kctls);
2679 *knew = ad1988_control_templates[type];
2680 knew->name = kstrdup(name, GFP_KERNEL);
2683 if (get_amp_nid_(val))
2684 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2685 knew->private_value = val;
2689 #define AD1988_PIN_CD_NID 0x18
2690 #define AD1988_PIN_BEEP_NID 0x10
2692 static hda_nid_t ad1988_mixer_nids[8] = {
2693 /* A B C D E F G H */
2694 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2697 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2699 static hda_nid_t idx_to_dac[8] = {
2700 /* A B C D E F G H */
2701 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2703 static hda_nid_t idx_to_dac_rev2[8] = {
2704 /* A B C D E F G H */
2705 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2708 return idx_to_dac_rev2[idx];
2710 return idx_to_dac[idx];
2713 static hda_nid_t ad1988_boost_nids[8] = {
2714 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2717 static int ad1988_pin_idx(hda_nid_t nid)
2719 static hda_nid_t ad1988_io_pins[8] = {
2720 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2723 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2724 if (ad1988_io_pins[i] == nid)
2726 return 0; /* should be -1 */
2729 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2731 static int loopback_idx[8] = {
2732 2, 0, 1, 3, 4, 5, 1, 4
2735 case AD1988_PIN_CD_NID:
2738 return loopback_idx[ad1988_pin_idx(nid)];
2742 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2744 static int adc_idx[8] = {
2745 0, 1, 2, 8, 4, 3, 6, 7
2748 case AD1988_PIN_CD_NID:
2751 return adc_idx[ad1988_pin_idx(nid)];
2755 /* fill in the dac_nids table from the parsed pin configuration */
2756 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2757 const struct auto_pin_cfg *cfg)
2759 struct ad198x_spec *spec = codec->spec;
2762 spec->multiout.dac_nids = spec->private_dac_nids;
2764 /* check the pins hardwired to audio widget */
2765 for (i = 0; i < cfg->line_outs; i++) {
2766 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2767 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2769 spec->multiout.num_dacs = cfg->line_outs;
2773 /* add playback controls from the parsed DAC table */
2774 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2775 const struct auto_pin_cfg *cfg)
2778 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2782 for (i = 0; i < cfg->line_outs; i++) {
2783 hda_nid_t dac = spec->multiout.dac_nids[i];
2786 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2789 err = add_control(spec, AD_CTL_WIDGET_VOL,
2790 "Center Playback Volume",
2791 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2794 err = add_control(spec, AD_CTL_WIDGET_VOL,
2795 "LFE Playback Volume",
2796 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2799 err = add_control(spec, AD_CTL_BIND_MUTE,
2800 "Center Playback Switch",
2801 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2804 err = add_control(spec, AD_CTL_BIND_MUTE,
2805 "LFE Playback Switch",
2806 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2810 sprintf(name, "%s Playback Volume", chname[i]);
2811 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2812 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2815 sprintf(name, "%s Playback Switch", chname[i]);
2816 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2817 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2825 /* add playback controls for speaker and HP outputs */
2826 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2829 struct ad198x_spec *spec = codec->spec;
2837 idx = ad1988_pin_idx(pin);
2838 nid = ad1988_idx_to_dac(codec, idx);
2839 /* check whether the corresponding DAC was already taken */
2840 for (i = 0; i < spec->autocfg.line_outs; i++) {
2841 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2842 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2846 if (i >= spec->autocfg.line_outs) {
2847 /* specify the DAC as the extra output */
2848 if (!spec->multiout.hp_nid)
2849 spec->multiout.hp_nid = nid;
2851 spec->multiout.extra_out_nid[0] = nid;
2852 /* control HP volume/switch on the output mixer amp */
2853 sprintf(name, "%s Playback Volume", pfx);
2854 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2855 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2859 nid = ad1988_mixer_nids[idx];
2860 sprintf(name, "%s Playback Switch", pfx);
2861 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2862 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2867 /* create input playback/capture controls for the given pin */
2868 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2869 const char *ctlname, int boost)
2874 sprintf(name, "%s Playback Volume", ctlname);
2875 idx = ad1988_pin_to_loopback_idx(pin);
2876 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2877 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2879 sprintf(name, "%s Playback Switch", ctlname);
2880 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2881 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2885 idx = ad1988_pin_idx(pin);
2886 bnid = ad1988_boost_nids[idx];
2888 sprintf(name, "%s Boost", ctlname);
2889 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2890 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2897 /* create playback/capture controls for input pins */
2898 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2899 const struct auto_pin_cfg *cfg)
2901 struct hda_input_mux *imux = &spec->private_imux;
2904 for (i = 0; i < AUTO_PIN_LAST; i++) {
2905 err = new_analog_input(spec, cfg->input_pins[i],
2906 auto_pin_cfg_labels[i],
2907 i <= AUTO_PIN_FRONT_MIC);
2910 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2911 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2914 imux->items[imux->num_items].label = "Mix";
2915 imux->items[imux->num_items].index = 9;
2918 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2919 "Analog Mix Playback Volume",
2920 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2922 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2923 "Analog Mix Playback Switch",
2924 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2930 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2931 hda_nid_t nid, int pin_type,
2935 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2936 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2938 case 0x11: /* port-A - DAC 04 */
2939 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2941 case 0x14: /* port-B - DAC 06 */
2942 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2944 case 0x15: /* port-C - DAC 05 */
2945 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2947 case 0x17: /* port-E - DAC 0a */
2948 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2950 case 0x13: /* mono - DAC 04 */
2951 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2956 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2958 struct ad198x_spec *spec = codec->spec;
2961 for (i = 0; i < spec->autocfg.line_outs; i++) {
2962 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2963 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2967 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2969 struct ad198x_spec *spec = codec->spec;
2972 pin = spec->autocfg.speaker_pins[0];
2973 if (pin) /* connect to front */
2974 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2975 pin = spec->autocfg.hp_pins[0];
2976 if (pin) /* connect to front */
2977 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2980 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2982 struct ad198x_spec *spec = codec->spec;
2985 for (i = 0; i < AUTO_PIN_LAST; i++) {
2986 hda_nid_t nid = spec->autocfg.input_pins[i];
2990 case 0x15: /* port-C */
2991 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2993 case 0x17: /* port-E */
2994 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2997 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2998 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2999 if (nid != AD1988_PIN_CD_NID)
3000 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3002 idx = ad1988_pin_idx(nid);
3003 if (ad1988_boost_nids[idx])
3004 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3005 AC_VERB_SET_AMP_GAIN_MUTE,
3010 /* parse the BIOS configuration and set up the alc_spec */
3011 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3012 static int ad1988_parse_auto_config(struct hda_codec *codec)
3014 struct ad198x_spec *spec = codec->spec;
3017 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3019 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3021 if (! spec->autocfg.line_outs)
3022 return 0; /* can't find valid BIOS pin config */
3023 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3024 (err = ad1988_auto_create_extra_out(codec,
3025 spec->autocfg.speaker_pins[0],
3027 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3028 "Headphone")) < 0 ||
3029 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3032 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3034 if (spec->autocfg.dig_outs)
3035 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3036 if (spec->autocfg.dig_in_pin)
3037 spec->dig_in_nid = AD1988_SPDIF_IN;
3039 if (spec->kctls.list)
3040 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3042 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3044 spec->input_mux = &spec->private_imux;
3049 /* init callback for auto-configuration model -- overriding the default init */
3050 static int ad1988_auto_init(struct hda_codec *codec)
3053 ad1988_auto_init_multi_out(codec);
3054 ad1988_auto_init_extra_out(codec);
3055 ad1988_auto_init_analog_input(codec);
3063 static const char *ad1988_models[AD1988_MODEL_LAST] = {
3064 [AD1988_6STACK] = "6stack",
3065 [AD1988_6STACK_DIG] = "6stack-dig",
3066 [AD1988_3STACK] = "3stack",
3067 [AD1988_3STACK_DIG] = "3stack-dig",
3068 [AD1988_LAPTOP] = "laptop",
3069 [AD1988_LAPTOP_DIG] = "laptop-dig",
3070 [AD1988_AUTO] = "auto",
3073 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
3074 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3075 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3076 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3077 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3081 static int patch_ad1988(struct hda_codec *codec)
3083 struct ad198x_spec *spec;
3084 int err, board_config;
3086 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3093 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3095 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3096 ad1988_models, ad1988_cfg_tbl);
3097 if (board_config < 0) {
3098 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3100 board_config = AD1988_AUTO;
3103 if (board_config == AD1988_AUTO) {
3104 /* automatic parse from the BIOS config */
3105 err = ad1988_parse_auto_config(codec);
3110 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3111 board_config = AD1988_6STACK;
3115 err = snd_hda_attach_beep_device(codec, 0x10);
3120 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3122 switch (board_config) {
3124 case AD1988_6STACK_DIG:
3125 spec->multiout.max_channels = 8;
3126 spec->multiout.num_dacs = 4;
3128 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3130 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3131 spec->input_mux = &ad1988_6stack_capture_source;
3132 spec->num_mixers = 2;
3134 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3136 spec->mixers[0] = ad1988_6stack_mixers1;
3137 spec->mixers[1] = ad1988_6stack_mixers2;
3138 spec->num_init_verbs = 1;
3139 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3140 if (board_config == AD1988_6STACK_DIG) {
3141 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3142 spec->dig_in_nid = AD1988_SPDIF_IN;
3146 case AD1988_3STACK_DIG:
3147 spec->multiout.max_channels = 6;
3148 spec->multiout.num_dacs = 3;
3150 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3152 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3153 spec->input_mux = &ad1988_6stack_capture_source;
3154 spec->channel_mode = ad1988_3stack_modes;
3155 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3156 spec->num_mixers = 2;
3158 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3160 spec->mixers[0] = ad1988_3stack_mixers1;
3161 spec->mixers[1] = ad1988_3stack_mixers2;
3162 spec->num_init_verbs = 1;
3163 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3164 if (board_config == AD1988_3STACK_DIG)
3165 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3168 case AD1988_LAPTOP_DIG:
3169 spec->multiout.max_channels = 2;
3170 spec->multiout.num_dacs = 1;
3171 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3172 spec->input_mux = &ad1988_laptop_capture_source;
3173 spec->num_mixers = 1;
3174 spec->mixers[0] = ad1988_laptop_mixers;
3175 spec->inv_eapd = 1; /* inverted EAPD */
3176 spec->num_init_verbs = 1;
3177 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3178 if (board_config == AD1988_LAPTOP_DIG)
3179 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3183 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3184 spec->adc_nids = ad1988_adc_nids;
3185 spec->capsrc_nids = ad1988_capsrc_nids;
3186 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3187 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3188 if (spec->multiout.dig_out_nid) {
3189 if (codec->vendor_id >= 0x11d4989a) {
3190 spec->mixers[spec->num_mixers++] =
3191 ad1989_spdif_out_mixers;
3192 spec->init_verbs[spec->num_init_verbs++] =
3193 ad1989_spdif_init_verbs;
3194 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3196 spec->mixers[spec->num_mixers++] =
3197 ad1988_spdif_out_mixers;
3198 spec->init_verbs[spec->num_init_verbs++] =
3199 ad1988_spdif_init_verbs;
3202 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3203 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3204 spec->init_verbs[spec->num_init_verbs++] =
3205 ad1988_spdif_in_init_verbs;
3208 codec->patch_ops = ad198x_patch_ops;
3209 switch (board_config) {
3211 codec->patch_ops.init = ad1988_auto_init;
3214 case AD1988_LAPTOP_DIG:
3215 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3218 #ifdef CONFIG_SND_HDA_POWER_SAVE
3219 spec->loopback.amplist = ad1988_loopbacks;
3221 spec->vmaster_nid = 0x04;
3230 * port-B - front line/mic-in
3231 * port-E - aux in/out
3232 * port-F - aux in/out
3233 * port-C - rear line/mic-in
3234 * port-D - rear line/hp-out
3235 * port-A - front line/hp-out
3237 * AD1984 = AD1884 + two digital mic-ins
3240 * For simplicity, we share the single DAC for both HP and line-outs
3241 * right now. The inidividual playbacks could be easily implemented,
3242 * but no build-up framework is given, so far.
3245 static hda_nid_t ad1884_dac_nids[1] = {
3249 static hda_nid_t ad1884_adc_nids[2] = {
3253 static hda_nid_t ad1884_capsrc_nids[2] = {
3257 #define AD1884_SPDIF_OUT 0x02
3259 static struct hda_input_mux ad1884_capture_source = {
3262 { "Front Mic", 0x0 },
3269 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3270 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3271 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3272 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3273 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3274 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3275 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3276 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3277 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3278 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3279 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3280 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3281 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3282 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3283 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3284 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3285 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3286 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3287 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3290 /* The multiple "Capture Source" controls confuse alsamixer
3291 * So call somewhat different..
3293 /* .name = "Capture Source", */
3294 .name = "Input Source",
3296 .info = ad198x_mux_enum_info,
3297 .get = ad198x_mux_enum_get,
3298 .put = ad198x_mux_enum_put,
3300 /* SPDIF controls */
3301 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3303 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3304 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3305 /* identical with ad1983 */
3306 .info = ad1983_spdif_route_info,
3307 .get = ad1983_spdif_route_get,
3308 .put = ad1983_spdif_route_put,
3313 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3314 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3315 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3316 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3318 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3324 * initialization verbs
3326 static struct hda_verb ad1884_init_verbs[] = {
3327 /* DACs; mute as default */
3328 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3329 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3330 /* Port-A (HP) mixer */
3331 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3332 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3334 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3335 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3336 /* HP selector - select DAC2 */
3337 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3338 /* Port-D (Line-out) mixer */
3339 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3340 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3342 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3343 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3344 /* Mono-out mixer */
3345 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3346 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3348 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3349 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3351 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3352 /* Port-B (front mic) pin */
3353 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3354 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3355 /* Port-C (rear mic) pin */
3356 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3357 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3358 /* Analog mixer; mute as default */
3359 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3360 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3361 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3362 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3363 /* Analog Mix output amp */
3364 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3365 /* SPDIF output selector */
3366 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3367 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3371 #ifdef CONFIG_SND_HDA_POWER_SAVE
3372 static struct hda_amp_list ad1884_loopbacks[] = {
3373 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3374 { 0x20, HDA_INPUT, 1 }, /* Mic */
3375 { 0x20, HDA_INPUT, 2 }, /* CD */
3376 { 0x20, HDA_INPUT, 4 }, /* Docking */
3381 static const char *ad1884_slave_vols[] = {
3382 "PCM Playback Volume",
3383 "Mic Playback Volume",
3384 "Mono Playback Volume",
3385 "Front Mic Playback Volume",
3386 "Mic Playback Volume",
3387 "CD Playback Volume",
3388 "Internal Mic Playback Volume",
3389 "Docking Mic Playback Volume",
3390 /* "Beep Playback Volume", */
3391 "IEC958 Playback Volume",
3395 static int patch_ad1884(struct hda_codec *codec)
3397 struct ad198x_spec *spec;
3400 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3406 err = snd_hda_attach_beep_device(codec, 0x10);
3411 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3413 spec->multiout.max_channels = 2;
3414 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3415 spec->multiout.dac_nids = ad1884_dac_nids;
3416 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3417 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3418 spec->adc_nids = ad1884_adc_nids;
3419 spec->capsrc_nids = ad1884_capsrc_nids;
3420 spec->input_mux = &ad1884_capture_source;
3421 spec->num_mixers = 1;
3422 spec->mixers[0] = ad1884_base_mixers;
3423 spec->num_init_verbs = 1;
3424 spec->init_verbs[0] = ad1884_init_verbs;
3425 spec->spdif_route = 0;
3426 #ifdef CONFIG_SND_HDA_POWER_SAVE
3427 spec->loopback.amplist = ad1884_loopbacks;
3429 spec->vmaster_nid = 0x04;
3430 /* we need to cover all playback volumes */
3431 spec->slave_vols = ad1884_slave_vols;
3433 codec->patch_ops = ad198x_patch_ops;
3439 * Lenovo Thinkpad T61/X61
3441 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3445 { "Internal Mic", 0x1 },
3447 { "Docking-Station", 0x4 },
3453 * Dell Precision T3400
3455 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3458 { "Front Mic", 0x0 },
3465 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3466 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3467 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3468 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3469 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3470 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3471 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3472 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3473 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3474 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3475 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3476 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3477 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3478 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3479 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3480 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3481 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3482 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3485 /* The multiple "Capture Source" controls confuse alsamixer
3486 * So call somewhat different..
3488 /* .name = "Capture Source", */
3489 .name = "Input Source",
3491 .info = ad198x_mux_enum_info,
3492 .get = ad198x_mux_enum_get,
3493 .put = ad198x_mux_enum_put,
3495 /* SPDIF controls */
3496 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3498 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3499 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3500 /* identical with ad1983 */
3501 .info = ad1983_spdif_route_info,
3502 .get = ad1983_spdif_route_get,
3503 .put = ad1983_spdif_route_put,
3508 /* additional verbs */
3509 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3510 /* Port-E (docking station mic) pin */
3511 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3512 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3513 /* docking mic boost */
3514 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3515 /* Analog mixer - docking mic; mute as default */
3516 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3517 /* enable EAPD bit */
3518 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3523 * Dell Precision T3400
3525 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3526 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3527 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3528 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3529 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3530 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3531 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3532 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3533 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3534 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3535 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3536 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3537 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3538 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3539 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3540 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3542 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3543 /* The multiple "Capture Source" controls confuse alsamixer
3544 * So call somewhat different..
3546 /* .name = "Capture Source", */
3547 .name = "Input Source",
3549 .info = ad198x_mux_enum_info,
3550 .get = ad198x_mux_enum_get,
3551 .put = ad198x_mux_enum_put,
3556 /* Digial MIC ADC NID 0x05 + 0x06 */
3557 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3558 struct hda_codec *codec,
3559 unsigned int stream_tag,
3560 unsigned int format,
3561 struct snd_pcm_substream *substream)
3563 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3564 stream_tag, 0, format);
3568 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3569 struct hda_codec *codec,
3570 struct snd_pcm_substream *substream)
3572 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3576 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3582 .prepare = ad1984_pcm_dmic_prepare,
3583 .cleanup = ad1984_pcm_dmic_cleanup
3587 static int ad1984_build_pcms(struct hda_codec *codec)
3589 struct ad198x_spec *spec = codec->spec;
3590 struct hda_pcm *info;
3593 err = ad198x_build_pcms(codec);
3597 info = spec->pcm_rec + codec->num_pcms;
3599 info->name = "AD1984 Digital Mic";
3600 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3608 AD1984_DELL_DESKTOP,
3612 static const char *ad1984_models[AD1984_MODELS] = {
3613 [AD1984_BASIC] = "basic",
3614 [AD1984_THINKPAD] = "thinkpad",
3615 [AD1984_DELL_DESKTOP] = "dell_desktop",
3618 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3619 /* Lenovo Thinkpad T61/X61 */
3620 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3621 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3625 static int patch_ad1984(struct hda_codec *codec)
3627 struct ad198x_spec *spec;
3628 int board_config, err;
3630 err = patch_ad1884(codec);
3634 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3635 ad1984_models, ad1984_cfg_tbl);
3636 switch (board_config) {
3638 /* additional digital mics */
3639 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3640 codec->patch_ops.build_pcms = ad1984_build_pcms;
3642 case AD1984_THINKPAD:
3643 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3644 spec->input_mux = &ad1984_thinkpad_capture_source;
3645 spec->mixers[0] = ad1984_thinkpad_mixers;
3646 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3648 case AD1984_DELL_DESKTOP:
3649 spec->multiout.dig_out_nid = 0;
3650 spec->input_mux = &ad1984_dell_desktop_capture_source;
3651 spec->mixers[0] = ad1984_dell_desktop_mixers;
3659 * AD1883 / AD1884A / AD1984A / AD1984B
3661 * port-B (0x14) - front mic-in
3662 * port-E (0x1c) - rear mic-in
3663 * port-F (0x16) - CD / ext out
3664 * port-C (0x15) - rear line-in
3665 * port-D (0x12) - rear line-out
3666 * port-A (0x11) - front hp-out
3668 * AD1984A = AD1884A + digital-mic
3669 * AD1883 = equivalent with AD1984A
3670 * AD1984B = AD1984A + extra SPDIF-out
3673 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3676 static hda_nid_t ad1884a_dac_nids[1] = {
3680 #define ad1884a_adc_nids ad1884_adc_nids
3681 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3683 #define AD1884A_SPDIF_OUT 0x02
3685 static struct hda_input_mux ad1884a_capture_source = {
3688 { "Front Mic", 0x0 },
3696 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3697 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3698 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3699 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3700 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3701 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3702 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3703 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3704 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3705 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3706 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3707 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3708 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3709 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3710 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3711 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3712 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3713 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3714 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3715 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3716 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3717 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3718 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3719 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3721 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3722 /* The multiple "Capture Source" controls confuse alsamixer
3723 * So call somewhat different..
3725 /* .name = "Capture Source", */
3726 .name = "Input Source",
3728 .info = ad198x_mux_enum_info,
3729 .get = ad198x_mux_enum_get,
3730 .put = ad198x_mux_enum_put,
3732 /* SPDIF controls */
3733 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3735 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3736 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3737 /* identical with ad1983 */
3738 .info = ad1983_spdif_route_info,
3739 .get = ad1983_spdif_route_get,
3740 .put = ad1983_spdif_route_put,
3746 * initialization verbs
3748 static struct hda_verb ad1884a_init_verbs[] = {
3749 /* DACs; unmute as default */
3750 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3751 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3752 /* Port-A (HP) mixer - route only from analog mixer */
3753 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3754 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3756 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3757 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3758 /* Port-D (Line-out) mixer - route only from analog mixer */
3759 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3760 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3762 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3763 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3764 /* Mono-out mixer - route only from analog mixer */
3765 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3766 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3768 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3769 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3770 /* Port-B (front mic) pin */
3771 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3772 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3773 /* Port-C (rear line-in) pin */
3774 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3775 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3776 /* Port-E (rear mic) pin */
3777 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3778 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3779 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3780 /* Port-F (CD) pin */
3781 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3782 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3783 /* Analog mixer; mute as default */
3784 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3785 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3786 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3787 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3788 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3789 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3790 /* Analog Mix output amp */
3791 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3792 /* capture sources */
3793 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3794 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3795 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3796 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3797 /* SPDIF output amp */
3798 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3802 #ifdef CONFIG_SND_HDA_POWER_SAVE
3803 static struct hda_amp_list ad1884a_loopbacks[] = {
3804 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3805 { 0x20, HDA_INPUT, 1 }, /* Mic */
3806 { 0x20, HDA_INPUT, 2 }, /* CD */
3807 { 0x20, HDA_INPUT, 4 }, /* Docking */
3815 * Port A: Headphone jack
3817 * Port C: Internal MIC
3818 * Port D: Dock Line Out (if enabled)
3819 * Port E: Dock Line In (if enabled)
3820 * Port F: Internal speakers
3823 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3824 struct snd_ctl_elem_value *ucontrol)
3826 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3827 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3828 int mute = (!ucontrol->value.integer.value[0] &&
3829 !ucontrol->value.integer.value[1]);
3830 /* toggle GPIO1 according to the mute state */
3831 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3836 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3837 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3839 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3840 .name = "Master Playback Switch",
3841 .subdevice = HDA_SUBDEV_AMP_FLAG,
3842 .info = snd_hda_mixer_amp_switch_info,
3843 .get = snd_hda_mixer_amp_switch_get,
3844 .put = ad1884a_mobile_master_sw_put,
3845 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3847 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3848 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3849 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3850 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3851 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3852 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3853 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3854 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3855 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3856 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3857 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3858 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3859 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3860 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3864 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3865 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3866 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3868 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3869 .name = "Master Playback Switch",
3870 .subdevice = HDA_SUBDEV_AMP_FLAG,
3871 .info = snd_hda_mixer_amp_switch_info,
3872 .get = snd_hda_mixer_amp_switch_get,
3873 .put = ad1884a_mobile_master_sw_put,
3874 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3876 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3877 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3878 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3879 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3880 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3881 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3885 /* mute internal speaker if HP is plugged */
3886 static void ad1884a_hp_automute(struct hda_codec *codec)
3888 unsigned int present;
3890 present = snd_hda_jack_detect(codec, 0x11);
3891 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3892 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3893 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3894 present ? 0x00 : 0x02);
3897 /* switch to external mic if plugged */
3898 static void ad1884a_hp_automic(struct hda_codec *codec)
3900 unsigned int present;
3902 present = snd_hda_jack_detect(codec, 0x14);
3903 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3907 #define AD1884A_HP_EVENT 0x37
3908 #define AD1884A_MIC_EVENT 0x36
3910 /* unsolicited event for HP jack sensing */
3911 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3913 switch (res >> 26) {
3914 case AD1884A_HP_EVENT:
3915 ad1884a_hp_automute(codec);
3917 case AD1884A_MIC_EVENT:
3918 ad1884a_hp_automic(codec);
3923 /* initialize jack-sensing, too */
3924 static int ad1884a_hp_init(struct hda_codec *codec)
3927 ad1884a_hp_automute(codec);
3928 ad1884a_hp_automic(codec);
3932 /* mute internal speaker if HP or docking HP is plugged */
3933 static void ad1884a_laptop_automute(struct hda_codec *codec)
3935 unsigned int present;
3937 present = snd_hda_jack_detect(codec, 0x11);
3939 present = snd_hda_jack_detect(codec, 0x12);
3940 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3941 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3942 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3943 present ? 0x00 : 0x02);
3946 /* switch to external mic if plugged */
3947 static void ad1884a_laptop_automic(struct hda_codec *codec)
3951 if (snd_hda_jack_detect(codec, 0x14))
3953 else if (snd_hda_jack_detect(codec, 0x1c))
3957 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3960 /* unsolicited event for HP jack sensing */
3961 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3964 switch (res >> 26) {
3965 case AD1884A_HP_EVENT:
3966 ad1884a_laptop_automute(codec);
3968 case AD1884A_MIC_EVENT:
3969 ad1884a_laptop_automic(codec);
3974 /* initialize jack-sensing, too */
3975 static int ad1884a_laptop_init(struct hda_codec *codec)
3978 ad1884a_laptop_automute(codec);
3979 ad1884a_laptop_automic(codec);
3983 /* additional verbs for laptop model */
3984 static struct hda_verb ad1884a_laptop_verbs[] = {
3985 /* Port-A (HP) pin - always unmuted */
3986 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3987 /* Port-F (int speaker) mixer - route only from analog mixer */
3988 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3989 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3990 /* Port-F (int speaker) pin */
3991 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3992 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3993 /* required for compaq 6530s/6531s speaker output */
3994 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3995 /* Port-C pin - internal mic-in */
3996 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3997 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3998 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3999 /* Port-D (docking line-out) pin - default unmuted */
4000 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4002 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4003 /* unsolicited event for pin-sense */
4004 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4005 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4006 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4007 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4008 /* allow to touch GPIO1 (for mute control) */
4009 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4010 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4011 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4015 static struct hda_verb ad1884a_mobile_verbs[] = {
4016 /* DACs; unmute as default */
4017 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4018 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4019 /* Port-A (HP) mixer - route only from analog mixer */
4020 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4021 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4023 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4024 /* Port-A (HP) pin - always unmuted */
4025 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4026 /* Port-B (mic jack) pin */
4027 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4028 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4029 /* Port-C (int mic) pin */
4030 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4031 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4032 /* Port-F (int speaker) mixer - route only from analog mixer */
4033 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4034 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4036 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4037 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4038 /* Analog mixer; mute as default */
4039 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4040 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4041 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4042 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4043 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4044 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4045 /* Analog Mix output amp */
4046 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4047 /* capture sources */
4048 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4049 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4050 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4051 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4052 /* unsolicited event for pin-sense */
4053 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4054 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4055 /* allow to touch GPIO1 (for mute control) */
4056 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4057 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4058 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4067 * 0x17 - built-in mic
4070 static struct hda_verb ad1984a_thinkpad_verbs[] = {
4072 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4074 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4076 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4077 /* unsolicited event for pin-sense */
4078 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4079 /* internal mic - dmic */
4080 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4081 /* set magic COEFs for dmic */
4082 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4083 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4087 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4088 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4089 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4090 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4091 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4092 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4093 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4094 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4095 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4096 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4097 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4099 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4100 .name = "Capture Source",
4101 .info = ad198x_mux_enum_info,
4102 .get = ad198x_mux_enum_get,
4103 .put = ad198x_mux_enum_put,
4108 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4112 { "Internal Mic", 0x5 },
4117 /* mute internal speaker if HP is plugged */
4118 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4120 unsigned int present;
4122 present = snd_hda_jack_detect(codec, 0x11);
4123 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4124 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4127 /* unsolicited event for HP jack sensing */
4128 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4131 if ((res >> 26) != AD1884A_HP_EVENT)
4133 ad1984a_thinkpad_automute(codec);
4136 /* initialize jack-sensing, too */
4137 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4140 ad1984a_thinkpad_automute(codec);
4146 * port-A (0x11) - front hp-out
4147 * port-B (0x14) - unused
4148 * port-C (0x15) - unused
4149 * port-D (0x12) - rear line out
4150 * port-E (0x1c) - front mic-in
4151 * port-F (0x16) - Internal speakers
4152 * digital-mic (0x17) - Internal mic
4155 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4156 /* DACs; unmute as default */
4157 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4158 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4159 /* Port-A (HP) mixer - route only from analog mixer */
4160 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4161 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4163 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4164 /* Port-A (HP) pin - always unmuted */
4165 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4166 /* Port-E (int speaker) mixer - route only from analog mixer */
4167 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4169 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4170 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4171 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4172 /* Port-F (int speaker) mixer - route only from analog mixer */
4173 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4174 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4176 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4177 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4178 /* Analog mixer; mute as default */
4179 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4180 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4181 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4182 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4183 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4184 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4185 /* Analog Mix output amp */
4186 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4187 /* capture sources */
4188 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4189 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4190 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4191 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4192 /* unsolicited event for pin-sense */
4193 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4194 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4195 /* allow to touch GPIO1 (for mute control) */
4196 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4197 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4198 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4199 /* internal mic - dmic */
4200 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4201 /* set magic COEFs for dmic */
4202 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4203 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4207 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4208 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4209 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4212 .subdevice = HDA_SUBDEV_AMP_FLAG,
4213 .name = "Master Playback Switch",
4214 .info = snd_hda_mixer_amp_switch_info,
4215 .get = snd_hda_mixer_amp_switch_get,
4216 .put = ad1884a_mobile_master_sw_put,
4217 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4219 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4220 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4221 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4222 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4223 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4224 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4228 /* switch to external mic if plugged */
4229 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4231 if (snd_hda_jack_detect(codec, 0x1c))
4232 snd_hda_codec_write(codec, 0x0c, 0,
4233 AC_VERB_SET_CONNECT_SEL, 0x4);
4235 snd_hda_codec_write(codec, 0x0c, 0,
4236 AC_VERB_SET_CONNECT_SEL, 0x5);
4240 /* unsolicited event for HP jack sensing */
4241 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4244 switch (res >> 26) {
4245 case AD1884A_HP_EVENT:
4246 ad1884a_hp_automute(codec);
4248 case AD1884A_MIC_EVENT:
4249 ad1984a_touchsmart_automic(codec);
4254 /* initialize jack-sensing, too */
4255 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4258 ad1884a_hp_automute(codec);
4259 ad1984a_touchsmart_automic(codec);
4276 static const char *ad1884a_models[AD1884A_MODELS] = {
4277 [AD1884A_DESKTOP] = "desktop",
4278 [AD1884A_LAPTOP] = "laptop",
4279 [AD1884A_MOBILE] = "mobile",
4280 [AD1884A_THINKPAD] = "thinkpad",
4281 [AD1984A_TOUCHSMART] = "touchsmart",
4284 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4285 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4286 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4287 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4288 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4289 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4290 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4291 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4292 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4293 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4294 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4298 static int patch_ad1884a(struct hda_codec *codec)
4300 struct ad198x_spec *spec;
4301 int err, board_config;
4303 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4309 err = snd_hda_attach_beep_device(codec, 0x10);
4314 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4316 spec->multiout.max_channels = 2;
4317 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4318 spec->multiout.dac_nids = ad1884a_dac_nids;
4319 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4320 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4321 spec->adc_nids = ad1884a_adc_nids;
4322 spec->capsrc_nids = ad1884a_capsrc_nids;
4323 spec->input_mux = &ad1884a_capture_source;
4324 spec->num_mixers = 1;
4325 spec->mixers[0] = ad1884a_base_mixers;
4326 spec->num_init_verbs = 1;
4327 spec->init_verbs[0] = ad1884a_init_verbs;
4328 spec->spdif_route = 0;
4329 #ifdef CONFIG_SND_HDA_POWER_SAVE
4330 spec->loopback.amplist = ad1884a_loopbacks;
4332 codec->patch_ops = ad198x_patch_ops;
4334 /* override some parameters */
4335 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4338 switch (board_config) {
4339 case AD1884A_LAPTOP:
4340 spec->mixers[0] = ad1884a_laptop_mixers;
4341 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4342 spec->multiout.dig_out_nid = 0;
4343 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4344 codec->patch_ops.init = ad1884a_laptop_init;
4345 /* set the upper-limit for mixer amp to 0dB for avoiding the
4346 * possible damage by overloading
4348 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4349 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4350 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4351 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4352 (1 << AC_AMPCAP_MUTE_SHIFT));
4354 case AD1884A_MOBILE:
4355 spec->mixers[0] = ad1884a_mobile_mixers;
4356 spec->init_verbs[0] = ad1884a_mobile_verbs;
4357 spec->multiout.dig_out_nid = 0;
4358 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4359 codec->patch_ops.init = ad1884a_hp_init;
4360 /* set the upper-limit for mixer amp to 0dB for avoiding the
4361 * possible damage by overloading
4363 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4364 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4365 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4366 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4367 (1 << AC_AMPCAP_MUTE_SHIFT));
4369 case AD1884A_THINKPAD:
4370 spec->mixers[0] = ad1984a_thinkpad_mixers;
4371 spec->init_verbs[spec->num_init_verbs++] =
4372 ad1984a_thinkpad_verbs;
4373 spec->multiout.dig_out_nid = 0;
4374 spec->input_mux = &ad1984a_thinkpad_capture_source;
4375 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4376 codec->patch_ops.init = ad1984a_thinkpad_init;
4378 case AD1984A_TOUCHSMART:
4379 spec->mixers[0] = ad1984a_touchsmart_mixers;
4380 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4381 spec->multiout.dig_out_nid = 0;
4382 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4383 codec->patch_ops.init = ad1984a_touchsmart_init;
4384 /* set the upper-limit for mixer amp to 0dB for avoiding the
4385 * possible damage by overloading
4387 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4388 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4389 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4390 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4391 (1 << AC_AMPCAP_MUTE_SHIFT));
4402 * port-A - front hp-out
4403 * port-B - front mic-in
4404 * port-C - rear line-in, shared surr-out (3stack)
4405 * port-D - rear line-out
4406 * port-E - rear mic-in, shared clfe-out (3stack)
4407 * port-F - rear surr-out (6stack)
4408 * port-G - rear clfe-out (6stack)
4411 static hda_nid_t ad1882_dac_nids[3] = {
4415 static hda_nid_t ad1882_adc_nids[2] = {
4419 static hda_nid_t ad1882_capsrc_nids[2] = {
4423 #define AD1882_SPDIF_OUT 0x02
4425 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4426 static struct hda_input_mux ad1882_capture_source = {
4429 { "Front Mic", 0x1 },
4437 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4438 static struct hda_input_mux ad1882a_capture_source = {
4441 { "Front Mic", 0x1 },
4444 { "Digital Mic", 0x06 },
4449 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4450 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4451 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4452 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4453 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4454 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4455 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4456 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4457 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4459 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4460 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4461 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4462 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4463 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4464 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4465 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4467 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4468 /* The multiple "Capture Source" controls confuse alsamixer
4469 * So call somewhat different..
4471 /* .name = "Capture Source", */
4472 .name = "Input Source",
4474 .info = ad198x_mux_enum_info,
4475 .get = ad198x_mux_enum_get,
4476 .put = ad198x_mux_enum_put,
4478 /* SPDIF controls */
4479 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4481 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4482 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4483 /* identical with ad1983 */
4484 .info = ad1983_spdif_route_info,
4485 .get = ad1983_spdif_route_get,
4486 .put = ad1983_spdif_route_put,
4491 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4492 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4493 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4494 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4495 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4496 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4497 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4498 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4499 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4503 static struct snd_kcontrol_new ad1882a_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, 0x04, HDA_INPUT),
4507 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4508 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4509 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4510 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4511 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4512 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4516 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4517 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4518 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4519 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4522 .name = "Channel Mode",
4523 .info = ad198x_ch_mode_info,
4524 .get = ad198x_ch_mode_get,
4525 .put = ad198x_ch_mode_put,
4530 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4531 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4532 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4533 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4537 static struct hda_verb ad1882_ch2_init[] = {
4538 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4539 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4540 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4541 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4542 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4543 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4547 static struct hda_verb ad1882_ch4_init[] = {
4548 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4549 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4550 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4551 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4552 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4553 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4557 static struct hda_verb ad1882_ch6_init[] = {
4558 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4559 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4560 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4561 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4562 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4563 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4567 static struct hda_channel_mode ad1882_modes[3] = {
4568 { 2, ad1882_ch2_init },
4569 { 4, ad1882_ch4_init },
4570 { 6, ad1882_ch6_init },
4574 * initialization verbs
4576 static struct hda_verb ad1882_init_verbs[] = {
4577 /* DACs; mute as default */
4578 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4579 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4580 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4581 /* Port-A (HP) mixer */
4582 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4583 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4585 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4586 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4587 /* HP selector - select DAC2 */
4588 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4589 /* Port-D (Line-out) mixer */
4590 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4591 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4593 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4594 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4595 /* Mono-out mixer */
4596 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4597 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4599 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4600 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4601 /* Port-B (front mic) pin */
4602 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4603 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4604 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4605 /* Port-C (line-in) pin */
4606 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4607 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4608 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4609 /* Port-C mixer - mute as input */
4610 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4611 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4612 /* Port-E (mic-in) pin */
4613 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4614 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4615 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4616 /* Port-E mixer - mute as input */
4617 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4618 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4619 /* Port-F (surround) */
4620 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4621 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4623 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4624 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4625 /* Analog mixer; mute as default */
4626 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4627 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4628 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4635 /* Analog Mix output amp */
4636 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4637 /* SPDIF output selector */
4638 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4639 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4640 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4644 #ifdef CONFIG_SND_HDA_POWER_SAVE
4645 static struct hda_amp_list ad1882_loopbacks[] = {
4646 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4647 { 0x20, HDA_INPUT, 1 }, /* Mic */
4648 { 0x20, HDA_INPUT, 4 }, /* Line */
4649 { 0x20, HDA_INPUT, 6 }, /* CD */
4661 static const char *ad1882_models[AD1986A_MODELS] = {
4662 [AD1882_3STACK] = "3stack",
4663 [AD1882_6STACK] = "6stack",
4667 static int patch_ad1882(struct hda_codec *codec)
4669 struct ad198x_spec *spec;
4670 int err, board_config;
4672 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4678 err = snd_hda_attach_beep_device(codec, 0x10);
4683 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4685 spec->multiout.max_channels = 6;
4686 spec->multiout.num_dacs = 3;
4687 spec->multiout.dac_nids = ad1882_dac_nids;
4688 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4689 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4690 spec->adc_nids = ad1882_adc_nids;
4691 spec->capsrc_nids = ad1882_capsrc_nids;
4692 if (codec->vendor_id == 0x11d41882)
4693 spec->input_mux = &ad1882_capture_source;
4695 spec->input_mux = &ad1882a_capture_source;
4696 spec->num_mixers = 2;
4697 spec->mixers[0] = ad1882_base_mixers;
4698 if (codec->vendor_id == 0x11d41882)
4699 spec->mixers[1] = ad1882_loopback_mixers;
4701 spec->mixers[1] = ad1882a_loopback_mixers;
4702 spec->num_init_verbs = 1;
4703 spec->init_verbs[0] = ad1882_init_verbs;
4704 spec->spdif_route = 0;
4705 #ifdef CONFIG_SND_HDA_POWER_SAVE
4706 spec->loopback.amplist = ad1882_loopbacks;
4708 spec->vmaster_nid = 0x04;
4710 codec->patch_ops = ad198x_patch_ops;
4712 /* override some parameters */
4713 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4714 ad1882_models, NULL);
4715 switch (board_config) {
4718 spec->num_mixers = 3;
4719 spec->mixers[2] = ad1882_3stack_mixers;
4720 spec->channel_mode = ad1882_modes;
4721 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4722 spec->need_dac_fix = 1;
4723 spec->multiout.max_channels = 2;
4724 spec->multiout.num_dacs = 1;
4727 spec->num_mixers = 3;
4728 spec->mixers[2] = ad1882_6stack_mixers;
4738 static struct hda_codec_preset snd_hda_preset_analog[] = {
4739 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4740 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4741 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4742 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4743 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4744 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4745 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4746 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4747 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4748 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4749 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4750 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4751 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4752 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4753 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4757 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4759 MODULE_LICENSE("GPL");
4760 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4762 static struct hda_codec_preset_list analog_list = {
4763 .preset = snd_hda_preset_analog,
4764 .owner = THIS_MODULE,
4767 static int __init patch_analog_init(void)
4769 return snd_hda_add_codec_preset(&analog_list);
4772 static void __exit patch_analog_exit(void)
4774 snd_hda_delete_codec_preset(&analog_list);
4777 module_init(patch_analog_init)
4778 module_exit(patch_analog_exit)