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"
30 #include "hda_patch.h"
33 struct snd_kcontrol_new *mixers[5];
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;
76 #ifdef CONFIG_SND_HDA_POWER_SAVE
77 struct hda_loopback_check loopback;
79 /* for virtual master */
80 hda_nid_t vmaster_nid;
81 const char **slave_vols;
82 const char **slave_sws;
86 * input MUX handling (common part)
88 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
90 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
91 struct ad198x_spec *spec = codec->spec;
93 return snd_hda_input_mux_info(spec->input_mux, uinfo);
96 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
98 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
99 struct ad198x_spec *spec = codec->spec;
100 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
102 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
106 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
108 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
109 struct ad198x_spec *spec = codec->spec;
110 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
112 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
113 spec->capsrc_nids[adc_idx],
114 &spec->cur_mux[adc_idx]);
118 * initialization (common callbacks)
120 static int ad198x_init(struct hda_codec *codec)
122 struct ad198x_spec *spec = codec->spec;
125 for (i = 0; i < spec->num_init_verbs; i++)
126 snd_hda_sequence_write(codec, spec->init_verbs[i]);
130 static const char *ad_slave_vols[] = {
131 "Front Playback Volume",
132 "Surround Playback Volume",
133 "Center Playback Volume",
134 "LFE Playback Volume",
135 "Side Playback Volume",
136 "Headphone Playback Volume",
137 "Mono Playback Volume",
138 "Speaker Playback Volume",
139 "IEC958 Playback Volume",
143 static const char *ad_slave_sws[] = {
144 "Front Playback Switch",
145 "Surround Playback Switch",
146 "Center Playback Switch",
147 "LFE Playback Switch",
148 "Side Playback Switch",
149 "Headphone Playback Switch",
150 "Mono Playback Switch",
151 "Speaker Playback Switch",
152 "IEC958 Playback Switch",
156 static void ad198x_free_kctls(struct hda_codec *codec);
158 static int ad198x_build_controls(struct hda_codec *codec)
160 struct ad198x_spec *spec = codec->spec;
164 for (i = 0; i < spec->num_mixers; i++) {
165 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
169 if (spec->multiout.dig_out_nid) {
170 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
173 err = snd_hda_create_spdif_share_sw(codec,
177 spec->multiout.share_spdif = 1;
179 if (spec->dig_in_nid) {
180 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
185 /* if we have no master control, let's create it */
186 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
187 unsigned int vmaster_tlv[4];
188 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
189 HDA_OUTPUT, vmaster_tlv);
190 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
193 spec->slave_vols : ad_slave_vols));
197 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
198 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
201 spec->slave_sws : ad_slave_sws));
206 ad198x_free_kctls(codec); /* no longer needed */
210 #ifdef CONFIG_SND_HDA_POWER_SAVE
211 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
213 struct ad198x_spec *spec = codec->spec;
214 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
219 * Analog playback callbacks
221 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
222 struct hda_codec *codec,
223 struct snd_pcm_substream *substream)
225 struct ad198x_spec *spec = codec->spec;
226 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
230 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
231 struct hda_codec *codec,
232 unsigned int stream_tag,
234 struct snd_pcm_substream *substream)
236 struct ad198x_spec *spec = codec->spec;
237 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
241 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
242 struct hda_codec *codec,
243 struct snd_pcm_substream *substream)
245 struct ad198x_spec *spec = codec->spec;
246 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
252 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
253 struct hda_codec *codec,
254 struct snd_pcm_substream *substream)
256 struct ad198x_spec *spec = codec->spec;
257 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
260 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
261 struct hda_codec *codec,
262 struct snd_pcm_substream *substream)
264 struct ad198x_spec *spec = codec->spec;
265 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
268 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
269 struct hda_codec *codec,
270 unsigned int stream_tag,
272 struct snd_pcm_substream *substream)
274 struct ad198x_spec *spec = codec->spec;
275 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
282 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
283 struct hda_codec *codec,
284 unsigned int stream_tag,
286 struct snd_pcm_substream *substream)
288 struct ad198x_spec *spec = codec->spec;
289 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
290 stream_tag, 0, format);
294 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
295 struct hda_codec *codec,
296 struct snd_pcm_substream *substream)
298 struct ad198x_spec *spec = codec->spec;
299 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
306 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
309 .channels_max = 6, /* changed later */
310 .nid = 0, /* fill later */
312 .open = ad198x_playback_pcm_open,
313 .prepare = ad198x_playback_pcm_prepare,
314 .cleanup = ad198x_playback_pcm_cleanup
318 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
322 .nid = 0, /* fill later */
324 .prepare = ad198x_capture_pcm_prepare,
325 .cleanup = ad198x_capture_pcm_cleanup
329 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
333 .nid = 0, /* fill later */
335 .open = ad198x_dig_playback_pcm_open,
336 .close = ad198x_dig_playback_pcm_close,
337 .prepare = ad198x_dig_playback_pcm_prepare
341 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
345 /* NID is set in alc_build_pcms */
348 static int ad198x_build_pcms(struct hda_codec *codec)
350 struct ad198x_spec *spec = codec->spec;
351 struct hda_pcm *info = spec->pcm_rec;
354 codec->pcm_info = info;
356 info->name = "AD198x Analog";
357 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
358 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
359 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
360 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
361 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
362 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
364 if (spec->multiout.dig_out_nid) {
367 info->name = "AD198x Digital";
368 info->pcm_type = HDA_PCM_TYPE_SPDIF;
369 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
370 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
371 if (spec->dig_in_nid) {
372 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
373 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
380 static void ad198x_free_kctls(struct hda_codec *codec)
382 struct ad198x_spec *spec = codec->spec;
384 if (spec->kctls.list) {
385 struct snd_kcontrol_new *kctl = spec->kctls.list;
387 for (i = 0; i < spec->kctls.used; i++)
390 snd_array_free(&spec->kctls);
393 static void ad198x_free(struct hda_codec *codec)
395 struct ad198x_spec *spec = codec->spec;
400 ad198x_free_kctls(codec);
404 static struct hda_codec_ops ad198x_patch_ops = {
405 .build_controls = ad198x_build_controls,
406 .build_pcms = ad198x_build_pcms,
409 #ifdef CONFIG_SND_HDA_POWER_SAVE
410 .check_power_status = ad198x_check_power_status,
417 * the private value = nid | (invert << 8)
419 #define ad198x_eapd_info snd_ctl_boolean_mono_info
421 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
422 struct snd_ctl_elem_value *ucontrol)
424 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
425 struct ad198x_spec *spec = codec->spec;
426 int invert = (kcontrol->private_value >> 8) & 1;
428 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
430 ucontrol->value.integer.value[0] = spec->cur_eapd;
434 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
435 struct snd_ctl_elem_value *ucontrol)
437 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
438 struct ad198x_spec *spec = codec->spec;
439 int invert = (kcontrol->private_value >> 8) & 1;
440 hda_nid_t nid = kcontrol->private_value & 0xff;
442 eapd = !!ucontrol->value.integer.value[0];
445 if (eapd == spec->cur_eapd)
447 spec->cur_eapd = eapd;
448 snd_hda_codec_write_cache(codec, nid,
449 0, AC_VERB_SET_EAPD_BTLENABLE,
454 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
455 struct snd_ctl_elem_info *uinfo);
456 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
457 struct snd_ctl_elem_value *ucontrol);
458 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
459 struct snd_ctl_elem_value *ucontrol);
466 #define AD1986A_SPDIF_OUT 0x02
467 #define AD1986A_FRONT_DAC 0x03
468 #define AD1986A_SURR_DAC 0x04
469 #define AD1986A_CLFE_DAC 0x05
470 #define AD1986A_ADC 0x06
472 static hda_nid_t ad1986a_dac_nids[3] = {
473 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
475 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
476 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
478 static struct hda_input_mux ad1986a_capture_source = {
492 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
493 .ops = &snd_hda_bind_vol,
495 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
496 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
497 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
502 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
503 .ops = &snd_hda_bind_sw,
505 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
506 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
507 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
515 static struct snd_kcontrol_new ad1986a_mixers[] = {
517 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
519 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
520 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
521 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
522 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
523 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
524 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
525 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
526 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
527 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
528 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
529 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
530 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
531 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
532 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
533 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
534 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
535 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
536 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
538 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
539 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
540 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
541 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
542 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
543 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
544 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
545 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
547 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
548 .name = "Capture Source",
549 .info = ad198x_mux_enum_info,
550 .get = ad198x_mux_enum_get,
551 .put = ad198x_mux_enum_put,
553 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
557 /* additional mixers for 3stack mode */
558 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
560 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
561 .name = "Channel Mode",
562 .info = ad198x_ch_mode_info,
563 .get = ad198x_ch_mode_get,
564 .put = ad198x_ch_mode_put,
569 /* laptop model - 2ch only */
570 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
572 /* master controls both pins 0x1a and 0x1b */
573 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
574 .ops = &snd_hda_bind_vol,
576 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
577 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
582 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
583 .ops = &snd_hda_bind_sw,
585 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
586 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
591 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
592 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
593 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
594 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
595 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
596 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
597 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
598 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
599 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
600 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
601 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
602 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
603 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
604 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
605 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
606 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
607 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
608 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
609 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
610 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
612 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
613 .name = "Capture Source",
614 .info = ad198x_mux_enum_info,
615 .get = ad198x_mux_enum_get,
616 .put = ad198x_mux_enum_put,
621 /* laptop-eapd model - 2ch only */
623 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
627 { "Internal Mic", 0x4 },
632 static struct hda_input_mux ad1986a_automic_capture_source = {
640 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
641 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
642 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
643 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
644 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
645 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
646 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
647 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
648 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
649 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
652 .name = "Capture Source",
653 .info = ad198x_mux_enum_info,
654 .get = ad198x_mux_enum_get,
655 .put = ad198x_mux_enum_put,
658 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
659 .name = "External Amplifier",
660 .info = ad198x_eapd_info,
661 .get = ad198x_eapd_get,
662 .put = ad198x_eapd_put,
663 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
668 /* re-connect the mic boost input according to the jack sensing */
669 static void ad1986a_automic(struct hda_codec *codec)
671 unsigned int present;
672 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
673 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
674 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
675 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
678 #define AD1986A_MIC_EVENT 0x36
680 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
683 if ((res >> 26) != AD1986A_MIC_EVENT)
685 ad1986a_automic(codec);
688 static int ad1986a_automic_init(struct hda_codec *codec)
691 ad1986a_automic(codec);
695 /* laptop-automute - 2ch only */
697 static void ad1986a_update_hp(struct hda_codec *codec)
699 struct ad198x_spec *spec = codec->spec;
702 if (spec->jack_present)
703 mute = HDA_AMP_MUTE; /* mute internal speaker */
705 /* unmute internal speaker if necessary */
706 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
707 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
711 static void ad1986a_hp_automute(struct hda_codec *codec)
713 struct ad198x_spec *spec = codec->spec;
714 unsigned int present;
716 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
717 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
718 spec->jack_present = !(present & 0x80000000);
719 ad1986a_update_hp(codec);
722 #define AD1986A_HP_EVENT 0x37
724 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
726 if ((res >> 26) != AD1986A_HP_EVENT)
728 ad1986a_hp_automute(codec);
731 static int ad1986a_hp_init(struct hda_codec *codec)
734 ad1986a_hp_automute(codec);
738 /* bind hp and internal speaker mute (with plug check) */
739 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
740 struct snd_ctl_elem_value *ucontrol)
742 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
743 long *valp = ucontrol->value.integer.value;
746 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
748 valp[0] ? 0 : HDA_AMP_MUTE);
749 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
751 valp[1] ? 0 : HDA_AMP_MUTE);
753 ad1986a_update_hp(codec);
757 static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
758 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
761 .name = "Master Playback Switch",
762 .info = snd_hda_mixer_amp_switch_info,
763 .get = snd_hda_mixer_amp_switch_get,
764 .put = ad1986a_hp_master_sw_put,
765 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
767 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
768 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
769 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
770 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
771 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
772 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
773 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
774 HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
775 HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
776 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
777 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
780 .name = "Capture Source",
781 .info = ad198x_mux_enum_info,
782 .get = ad198x_mux_enum_get,
783 .put = ad198x_mux_enum_put,
786 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
787 .name = "External Amplifier",
788 .info = ad198x_eapd_info,
789 .get = ad198x_eapd_get,
790 .put = ad198x_eapd_put,
791 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
797 * initialization verbs
799 static struct hda_verb ad1986a_init_verbs[] = {
800 /* Front, Surround, CLFE DAC; mute as default */
801 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
802 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
803 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
805 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
806 /* HP, Line-Out, Surround, CLFE selectors */
807 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
808 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
809 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
810 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
812 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
813 /* Mic selector: Mic 1/2 pin */
814 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
815 /* Line-in selector: Line-in */
816 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
818 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
819 /* Record selector: mic */
820 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
821 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
822 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
823 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
824 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
825 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
826 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
828 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
829 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
830 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
831 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
832 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
833 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
834 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
836 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
837 /* Front, Surround, CLFE Pins */
838 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
839 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
840 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
842 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
844 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
845 /* Line, Aux, CD, Beep-In Pin */
846 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
847 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
848 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
849 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
850 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
854 static struct hda_verb ad1986a_ch2_init[] = {
855 /* Surround out -> Line In */
856 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
857 /* Line-in selectors */
858 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
860 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
861 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
862 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
866 static struct hda_verb ad1986a_ch4_init[] = {
867 /* Surround out -> Surround */
868 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
869 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
871 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
872 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
876 static struct hda_verb ad1986a_ch6_init[] = {
877 /* Surround out -> Surround out */
878 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
879 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
881 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
882 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
886 static struct hda_channel_mode ad1986a_modes[3] = {
887 { 2, ad1986a_ch2_init },
888 { 4, ad1986a_ch4_init },
889 { 6, ad1986a_ch6_init },
892 /* eapd initialization */
893 static struct hda_verb ad1986a_eapd_init_verbs[] = {
894 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
898 static struct hda_verb ad1986a_automic_verbs[] = {
899 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
900 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
901 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
902 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
903 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
907 /* Ultra initialization */
908 static struct hda_verb ad1986a_ultra_init[] = {
909 /* eapd initialization */
910 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
912 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
913 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
914 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
918 /* pin sensing on HP jack */
919 static struct hda_verb ad1986a_hp_init_verbs[] = {
920 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
931 AD1986A_LAPTOP_AUTOMUTE,
936 static const char *ad1986a_models[AD1986A_MODELS] = {
937 [AD1986A_6STACK] = "6stack",
938 [AD1986A_3STACK] = "3stack",
939 [AD1986A_LAPTOP] = "laptop",
940 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
941 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
942 [AD1986A_ULTRA] = "ultra",
945 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
946 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
947 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
948 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
949 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
950 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
951 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
952 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
953 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
954 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
955 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
956 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
957 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
958 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
959 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
960 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
961 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
962 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
963 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
964 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
965 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
966 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
967 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
968 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
969 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
970 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
971 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
972 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
973 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
977 #ifdef CONFIG_SND_HDA_POWER_SAVE
978 static struct hda_amp_list ad1986a_loopbacks[] = {
979 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
980 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
981 { 0x15, HDA_OUTPUT, 0 }, /* CD */
982 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
983 { 0x17, HDA_OUTPUT, 0 }, /* Line */
988 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
990 unsigned int conf = snd_hda_codec_read(codec, nid, 0,
991 AC_VERB_GET_CONFIG_DEFAULT, 0);
992 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
995 static int patch_ad1986a(struct hda_codec *codec)
997 struct ad198x_spec *spec;
1000 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1006 spec->multiout.max_channels = 6;
1007 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1008 spec->multiout.dac_nids = ad1986a_dac_nids;
1009 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1010 spec->num_adc_nids = 1;
1011 spec->adc_nids = ad1986a_adc_nids;
1012 spec->capsrc_nids = ad1986a_capsrc_nids;
1013 spec->input_mux = &ad1986a_capture_source;
1014 spec->num_mixers = 1;
1015 spec->mixers[0] = ad1986a_mixers;
1016 spec->num_init_verbs = 1;
1017 spec->init_verbs[0] = ad1986a_init_verbs;
1018 #ifdef CONFIG_SND_HDA_POWER_SAVE
1019 spec->loopback.amplist = ad1986a_loopbacks;
1021 spec->vmaster_nid = 0x1b;
1023 codec->patch_ops = ad198x_patch_ops;
1025 /* override some parameters */
1026 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1029 switch (board_config) {
1030 case AD1986A_3STACK:
1031 spec->num_mixers = 2;
1032 spec->mixers[1] = ad1986a_3st_mixers;
1033 spec->num_init_verbs = 2;
1034 spec->init_verbs[1] = ad1986a_ch2_init;
1035 spec->channel_mode = ad1986a_modes;
1036 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1037 spec->need_dac_fix = 1;
1038 spec->multiout.max_channels = 2;
1039 spec->multiout.num_dacs = 1;
1041 case AD1986A_LAPTOP:
1042 spec->mixers[0] = ad1986a_laptop_mixers;
1043 spec->multiout.max_channels = 2;
1044 spec->multiout.num_dacs = 1;
1045 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1047 case AD1986A_LAPTOP_EAPD:
1048 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1049 spec->num_init_verbs = 3;
1050 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1051 spec->init_verbs[2] = ad1986a_automic_verbs;
1052 spec->multiout.max_channels = 2;
1053 spec->multiout.num_dacs = 1;
1054 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1055 if (!is_jack_available(codec, 0x25))
1056 spec->multiout.dig_out_nid = 0;
1057 spec->input_mux = &ad1986a_automic_capture_source;
1058 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1059 codec->patch_ops.init = ad1986a_automic_init;
1061 case AD1986A_LAPTOP_AUTOMUTE:
1062 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1063 spec->num_init_verbs = 3;
1064 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1065 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1066 spec->multiout.max_channels = 2;
1067 spec->multiout.num_dacs = 1;
1068 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1069 if (!is_jack_available(codec, 0x25))
1070 spec->multiout.dig_out_nid = 0;
1071 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1072 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1073 codec->patch_ops.init = ad1986a_hp_init;
1076 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1077 spec->num_init_verbs = 2;
1078 spec->init_verbs[1] = ad1986a_ultra_init;
1079 spec->multiout.max_channels = 2;
1080 spec->multiout.num_dacs = 1;
1081 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1082 spec->multiout.dig_out_nid = 0;
1086 /* AD1986A has a hardware problem that it can't share a stream
1087 * with multiple output pins. The copy of front to surrounds
1088 * causes noisy or silent outputs at a certain timing, e.g.
1089 * changing the volume.
1090 * So, let's disable the shared stream.
1092 spec->multiout.no_share_stream = 1;
1101 #define AD1983_SPDIF_OUT 0x02
1102 #define AD1983_DAC 0x03
1103 #define AD1983_ADC 0x04
1105 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1106 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1107 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1109 static struct hda_input_mux ad1983_capture_source = {
1115 { "Mix Mono", 0x3 },
1120 * SPDIF playback route
1122 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1124 static char *texts[] = { "PCM", "ADC" };
1126 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1128 uinfo->value.enumerated.items = 2;
1129 if (uinfo->value.enumerated.item > 1)
1130 uinfo->value.enumerated.item = 1;
1131 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1135 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1137 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1138 struct ad198x_spec *spec = codec->spec;
1140 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1144 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1146 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1147 struct ad198x_spec *spec = codec->spec;
1149 if (ucontrol->value.enumerated.item[0] > 1)
1151 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1152 spec->spdif_route = ucontrol->value.enumerated.item[0];
1153 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1154 AC_VERB_SET_CONNECT_SEL,
1161 static struct snd_kcontrol_new ad1983_mixers[] = {
1162 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1163 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1164 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1165 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1166 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1167 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1168 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1169 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1170 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1171 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1172 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1173 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1174 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
1175 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
1176 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1177 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1178 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1180 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1181 .name = "Capture Source",
1182 .info = ad198x_mux_enum_info,
1183 .get = ad198x_mux_enum_get,
1184 .put = ad198x_mux_enum_put,
1187 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1188 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1189 .info = ad1983_spdif_route_info,
1190 .get = ad1983_spdif_route_get,
1191 .put = ad1983_spdif_route_put,
1196 static struct hda_verb ad1983_init_verbs[] = {
1197 /* Front, HP, Mono; mute as default */
1198 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1199 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1200 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1201 /* Beep, PCM, Mic, Line-In: mute */
1202 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1203 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1204 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1205 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1206 /* Front, HP selectors; from Mix */
1207 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1208 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1209 /* Mono selector; from Mix */
1210 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1211 /* Mic selector; Mic */
1212 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1213 /* Line-in selector: Line-in */
1214 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1215 /* Mic boost: 0dB */
1216 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1217 /* Record selector: mic */
1218 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1219 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1220 /* SPDIF route: PCM */
1221 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1223 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1225 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1227 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1229 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1231 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1235 #ifdef CONFIG_SND_HDA_POWER_SAVE
1236 static struct hda_amp_list ad1983_loopbacks[] = {
1237 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1238 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1243 static int patch_ad1983(struct hda_codec *codec)
1245 struct ad198x_spec *spec;
1247 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1253 spec->multiout.max_channels = 2;
1254 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1255 spec->multiout.dac_nids = ad1983_dac_nids;
1256 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1257 spec->num_adc_nids = 1;
1258 spec->adc_nids = ad1983_adc_nids;
1259 spec->capsrc_nids = ad1983_capsrc_nids;
1260 spec->input_mux = &ad1983_capture_source;
1261 spec->num_mixers = 1;
1262 spec->mixers[0] = ad1983_mixers;
1263 spec->num_init_verbs = 1;
1264 spec->init_verbs[0] = ad1983_init_verbs;
1265 spec->spdif_route = 0;
1266 #ifdef CONFIG_SND_HDA_POWER_SAVE
1267 spec->loopback.amplist = ad1983_loopbacks;
1269 spec->vmaster_nid = 0x05;
1271 codec->patch_ops = ad198x_patch_ops;
1278 * AD1981 HD specific
1281 #define AD1981_SPDIF_OUT 0x02
1282 #define AD1981_DAC 0x03
1283 #define AD1981_ADC 0x04
1285 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1286 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1287 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1289 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1290 static struct hda_input_mux ad1981_capture_source = {
1293 { "Front Mic", 0x0 },
1296 { "Mix Mono", 0x3 },
1303 static struct snd_kcontrol_new ad1981_mixers[] = {
1304 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1305 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1306 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1307 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1308 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1309 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1310 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1311 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1312 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1313 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1314 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1315 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1316 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1317 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1318 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1319 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1320 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1321 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1322 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1323 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
1324 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1325 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1326 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1327 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1329 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1330 .name = "Capture Source",
1331 .info = ad198x_mux_enum_info,
1332 .get = ad198x_mux_enum_get,
1333 .put = ad198x_mux_enum_put,
1335 /* identical with AD1983 */
1337 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1338 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1339 .info = ad1983_spdif_route_info,
1340 .get = ad1983_spdif_route_get,
1341 .put = ad1983_spdif_route_put,
1346 static struct hda_verb ad1981_init_verbs[] = {
1347 /* Front, HP, Mono; mute as default */
1348 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1349 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1350 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1351 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1352 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1353 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1354 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1355 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1356 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1357 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1358 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1359 /* Front, HP selectors; from Mix */
1360 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1361 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1362 /* Mono selector; from Mix */
1363 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1364 /* Mic Mixer; select Front Mic */
1365 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1366 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1367 /* Mic boost: 0dB */
1368 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1369 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1370 /* Record selector: Front mic */
1371 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1372 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1373 /* SPDIF route: PCM */
1374 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1376 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1378 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1380 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1381 /* Front & Rear Mic Pins */
1382 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1383 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1385 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1387 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1388 /* Line-Out as Input: disabled */
1389 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1393 #ifdef CONFIG_SND_HDA_POWER_SAVE
1394 static struct hda_amp_list ad1981_loopbacks[] = {
1395 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1396 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1397 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1398 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1399 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1405 * Patch for HP nx6320
1407 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1408 * speaker output enabled _and_ mute-LED off.
1411 #define AD1981_HP_EVENT 0x37
1412 #define AD1981_MIC_EVENT 0x38
1414 static struct hda_verb ad1981_hp_init_verbs[] = {
1415 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1416 /* pin sensing on HP and Mic jacks */
1417 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1418 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1422 /* turn on/off EAPD (+ mute HP) as a master switch */
1423 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1424 struct snd_ctl_elem_value *ucontrol)
1426 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1427 struct ad198x_spec *spec = codec->spec;
1429 if (! ad198x_eapd_put(kcontrol, ucontrol))
1431 /* change speaker pin appropriately */
1432 snd_hda_codec_write(codec, 0x05, 0,
1433 AC_VERB_SET_PIN_WIDGET_CONTROL,
1434 spec->cur_eapd ? PIN_OUT : 0);
1435 /* toggle HP mute appropriately */
1436 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1438 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1442 /* bind volumes of both NID 0x05 and 0x06 */
1443 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1444 .ops = &snd_hda_bind_vol,
1446 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1447 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1452 /* mute internal speaker if HP is plugged */
1453 static void ad1981_hp_automute(struct hda_codec *codec)
1455 unsigned int present;
1457 present = snd_hda_codec_read(codec, 0x06, 0,
1458 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1459 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1460 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1463 /* toggle input of built-in and mic jack appropriately */
1464 static void ad1981_hp_automic(struct hda_codec *codec)
1466 static struct hda_verb mic_jack_on[] = {
1467 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1468 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1471 static struct hda_verb mic_jack_off[] = {
1472 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1473 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1476 unsigned int present;
1478 present = snd_hda_codec_read(codec, 0x08, 0,
1479 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1481 snd_hda_sequence_write(codec, mic_jack_on);
1483 snd_hda_sequence_write(codec, mic_jack_off);
1486 /* unsolicited event for HP jack sensing */
1487 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1492 case AD1981_HP_EVENT:
1493 ad1981_hp_automute(codec);
1495 case AD1981_MIC_EVENT:
1496 ad1981_hp_automic(codec);
1501 static struct hda_input_mux ad1981_hp_capture_source = {
1505 { "Docking-Station", 0x1 },
1510 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1511 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1514 .name = "Master Playback Switch",
1515 .info = ad198x_eapd_info,
1516 .get = ad198x_eapd_get,
1517 .put = ad1981_hp_master_sw_put,
1518 .private_value = 0x05,
1520 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1521 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1523 /* FIXME: analog mic/line loopback doesn't work with my tests...
1524 * (although recording is OK)
1526 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1527 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1528 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1529 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1530 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1531 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1532 /* FIXME: does this laptop have analog CD connection? */
1533 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1534 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1536 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1537 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1538 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1539 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1541 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1542 .name = "Capture Source",
1543 .info = ad198x_mux_enum_info,
1544 .get = ad198x_mux_enum_get,
1545 .put = ad198x_mux_enum_put,
1550 /* initialize jack-sensing, too */
1551 static int ad1981_hp_init(struct hda_codec *codec)
1554 ad1981_hp_automute(codec);
1555 ad1981_hp_automic(codec);
1559 /* configuration for Toshiba Laptops */
1560 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1561 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1562 /* pin sensing on HP and Mic jacks */
1563 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1564 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1568 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1569 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1570 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1574 /* configuration for Lenovo Thinkpad T60 */
1575 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1576 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1577 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1578 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1579 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1580 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1581 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1582 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1583 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1584 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1585 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1586 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1588 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1589 .name = "Capture Source",
1590 .info = ad198x_mux_enum_info,
1591 .get = ad198x_mux_enum_get,
1592 .put = ad198x_mux_enum_put,
1594 /* identical with AD1983 */
1596 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1597 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1598 .info = ad1983_spdif_route_info,
1599 .get = ad1983_spdif_route_get,
1600 .put = ad1983_spdif_route_put,
1605 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1623 static const char *ad1981_models[AD1981_MODELS] = {
1625 [AD1981_THINKPAD] = "thinkpad",
1626 [AD1981_BASIC] = "basic",
1627 [AD1981_TOSHIBA] = "toshiba"
1630 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1631 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1632 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1634 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
1635 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1636 /* Lenovo Thinkpad T60/X60/Z6xx */
1637 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
1638 /* HP nx6320 (reversed SSID, H/W bug) */
1639 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1643 static int patch_ad1981(struct hda_codec *codec)
1645 struct ad198x_spec *spec;
1648 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1654 spec->multiout.max_channels = 2;
1655 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1656 spec->multiout.dac_nids = ad1981_dac_nids;
1657 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1658 spec->num_adc_nids = 1;
1659 spec->adc_nids = ad1981_adc_nids;
1660 spec->capsrc_nids = ad1981_capsrc_nids;
1661 spec->input_mux = &ad1981_capture_source;
1662 spec->num_mixers = 1;
1663 spec->mixers[0] = ad1981_mixers;
1664 spec->num_init_verbs = 1;
1665 spec->init_verbs[0] = ad1981_init_verbs;
1666 spec->spdif_route = 0;
1667 #ifdef CONFIG_SND_HDA_POWER_SAVE
1668 spec->loopback.amplist = ad1981_loopbacks;
1670 spec->vmaster_nid = 0x05;
1672 codec->patch_ops = ad198x_patch_ops;
1674 /* override some parameters */
1675 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1678 switch (board_config) {
1680 spec->mixers[0] = ad1981_hp_mixers;
1681 spec->num_init_verbs = 2;
1682 spec->init_verbs[1] = ad1981_hp_init_verbs;
1683 spec->multiout.dig_out_nid = 0;
1684 spec->input_mux = &ad1981_hp_capture_source;
1686 codec->patch_ops.init = ad1981_hp_init;
1687 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1689 case AD1981_THINKPAD:
1690 spec->mixers[0] = ad1981_thinkpad_mixers;
1691 spec->input_mux = &ad1981_thinkpad_capture_source;
1693 case AD1981_TOSHIBA:
1694 spec->mixers[0] = ad1981_hp_mixers;
1695 spec->mixers[1] = ad1981_toshiba_mixers;
1696 spec->num_init_verbs = 2;
1697 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1698 spec->multiout.dig_out_nid = 0;
1699 spec->input_mux = &ad1981_hp_capture_source;
1700 codec->patch_ops.init = ad1981_hp_init;
1701 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1711 * Output pins and routes
1713 * Pin Mix Sel DAC (*)
1714 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1715 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1716 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1717 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1718 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1719 * port-F 0x16 (mute) <- 0x2a <- 06
1720 * port-G 0x24 (mute) <- 0x27 <- 05
1721 * port-H 0x25 (mute) <- 0x28 <- 0a
1722 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1724 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1725 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1727 * Input pins and routes
1729 * pin boost mix input # / adc input #
1730 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1731 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1732 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1733 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1734 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1735 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1736 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1737 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1741 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1742 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1744 * Inputs of Analog Mix (0x20)
1745 * 0:Port-B (front mic)
1746 * 1:Port-C/G/H (line-in)
1748 * 3:Port-D (line-in/2)
1749 * 4:Port-E/G/H (mic-in)
1750 * 5:Port-F (mic2-in)
1756 * 1:Port-B (front mic-in)
1757 * 2:Port-C (line-in)
1758 * 3:Port-F (mic2-in)
1763 * 8:Port-D (line-in/2)
1766 * Proposed pin assignments by the datasheet
1769 * Port-A front headphone
1779 * Port-A front headphone
1781 * C rear line-in/surround
1783 * E rear mic-in/CLFE
1789 * D internal speaker (with EAPD)
1790 * E/F quad mic array
1806 /* reivision id to check workarounds */
1807 #define AD1988A_REV2 0x100200
1809 #define is_rev2(codec) \
1810 ((codec)->vendor_id == 0x11d41988 && \
1811 (codec)->revision_id == AD1988A_REV2)
1817 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1818 0x04, 0x06, 0x05, 0x0a
1821 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1825 /* for AD1988A revision-2, DAC2-4 are swapped */
1826 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1827 0x04, 0x05, 0x0a, 0x06
1830 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1834 static hda_nid_t ad1988_adc_nids[3] = {
1838 static hda_nid_t ad1988_capsrc_nids[3] = {
1842 #define AD1988_SPDIF_OUT 0x02
1843 #define AD1988_SPDIF_OUT_HDMI 0x0b
1844 #define AD1988_SPDIF_IN 0x07
1846 static hda_nid_t ad1989b_slave_dig_outs[2] = {
1847 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI
1850 static struct hda_input_mux ad1988_6stack_capture_source = {
1853 { "Front Mic", 0x1 }, /* port-B */
1854 { "Line", 0x2 }, /* port-C */
1855 { "Mic", 0x4 }, /* port-E */
1861 static struct hda_input_mux ad1988_laptop_capture_source = {
1864 { "Mic/Line", 0x1 }, /* port-B */
1872 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1873 struct snd_ctl_elem_info *uinfo)
1875 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1876 struct ad198x_spec *spec = codec->spec;
1877 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1878 spec->num_channel_mode);
1881 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1882 struct snd_ctl_elem_value *ucontrol)
1884 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1885 struct ad198x_spec *spec = codec->spec;
1886 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1887 spec->num_channel_mode, spec->multiout.max_channels);
1890 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1891 struct snd_ctl_elem_value *ucontrol)
1893 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1894 struct ad198x_spec *spec = codec->spec;
1895 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1896 spec->num_channel_mode,
1897 &spec->multiout.max_channels);
1898 if (err >= 0 && spec->need_dac_fix)
1899 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1904 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1905 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1906 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1907 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1908 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1909 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1913 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
1914 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1915 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1916 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1917 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
1918 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1922 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
1923 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1924 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1925 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1926 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1927 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1928 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1929 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1931 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1932 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1933 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1934 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1935 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1936 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1937 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1938 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1940 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1941 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1943 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1944 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1946 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1947 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1953 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
1954 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1955 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1956 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1957 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1961 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
1962 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1963 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1964 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
1965 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
1969 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
1970 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1971 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
1972 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
1973 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
1974 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1975 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1977 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1978 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1979 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1980 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1981 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1982 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1983 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1984 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1986 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1987 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1989 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1990 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1992 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1993 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1995 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1996 .name = "Channel Mode",
1997 .info = ad198x_ch_mode_info,
1998 .get = ad198x_ch_mode_get,
1999 .put = ad198x_ch_mode_put,
2006 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2007 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2008 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2009 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2011 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2012 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2013 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2014 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2015 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2016 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2018 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
2019 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2021 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2022 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2024 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2027 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2028 .name = "External Amplifier",
2029 .info = ad198x_eapd_info,
2030 .get = ad198x_eapd_get,
2031 .put = ad198x_eapd_put,
2032 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2039 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2040 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2041 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2042 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2043 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2044 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2045 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2047 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2048 /* The multiple "Capture Source" controls confuse alsamixer
2049 * So call somewhat different..
2051 /* .name = "Capture Source", */
2052 .name = "Input Source",
2054 .info = ad198x_mux_enum_info,
2055 .get = ad198x_mux_enum_get,
2056 .put = ad198x_mux_enum_put,
2061 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2062 struct snd_ctl_elem_info *uinfo)
2064 static char *texts[] = {
2065 "PCM", "ADC1", "ADC2", "ADC3"
2067 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2069 uinfo->value.enumerated.items = 4;
2070 if (uinfo->value.enumerated.item >= 4)
2071 uinfo->value.enumerated.item = 3;
2072 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2076 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2077 struct snd_ctl_elem_value *ucontrol)
2079 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2082 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2085 ucontrol->value.enumerated.item[0] = 0;
2087 sel = snd_hda_codec_read(codec, 0x0b, 0,
2088 AC_VERB_GET_CONNECT_SEL, 0);
2093 ucontrol->value.enumerated.item[0] = sel;
2098 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2099 struct snd_ctl_elem_value *ucontrol)
2101 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2102 unsigned int val, sel;
2105 val = ucontrol->value.enumerated.item[0];
2109 sel = snd_hda_codec_read(codec, 0x1d, 0,
2110 AC_VERB_GET_AMP_GAIN_MUTE,
2112 change = sel & 0x80;
2114 snd_hda_codec_write_cache(codec, 0x1d, 0,
2115 AC_VERB_SET_AMP_GAIN_MUTE,
2117 snd_hda_codec_write_cache(codec, 0x1d, 0,
2118 AC_VERB_SET_AMP_GAIN_MUTE,
2122 sel = snd_hda_codec_read(codec, 0x1d, 0,
2123 AC_VERB_GET_AMP_GAIN_MUTE,
2124 AC_AMP_GET_INPUT | 0x01);
2125 change = sel & 0x80;
2127 snd_hda_codec_write_cache(codec, 0x1d, 0,
2128 AC_VERB_SET_AMP_GAIN_MUTE,
2130 snd_hda_codec_write_cache(codec, 0x1d, 0,
2131 AC_VERB_SET_AMP_GAIN_MUTE,
2134 sel = snd_hda_codec_read(codec, 0x0b, 0,
2135 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2136 change |= sel != val;
2138 snd_hda_codec_write_cache(codec, 0x0b, 0,
2139 AC_VERB_SET_CONNECT_SEL,
2145 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2146 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2148 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2149 .name = "IEC958 Playback Source",
2150 .info = ad1988_spdif_playback_source_info,
2151 .get = ad1988_spdif_playback_source_get,
2152 .put = ad1988_spdif_playback_source_put,
2157 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2158 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2162 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2163 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2164 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2169 * initialization verbs
2173 * for 6-stack (+dig)
2175 static struct hda_verb ad1988_6stack_init_verbs[] = {
2176 /* Front, Surround, CLFE, side DAC; unmute as default */
2177 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2178 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2179 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2180 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2181 /* Port-A front headphon path */
2182 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2183 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2184 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2185 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2186 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2187 /* Port-D line-out path */
2188 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2189 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2190 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2191 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2192 /* Port-F surround path */
2193 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2194 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2195 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2196 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2197 /* Port-G CLFE path */
2198 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2199 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2200 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2201 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2202 /* Port-H side path */
2203 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2204 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2205 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2206 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2208 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2209 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2210 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2211 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2212 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2213 /* Port-B front mic-in path */
2214 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2215 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2216 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2217 /* Port-C line-in path */
2218 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2219 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2220 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2221 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2222 /* Port-E mic-in path */
2223 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2224 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2225 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2226 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2227 /* Analog CD Input */
2228 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2229 /* Analog Mix output amp */
2230 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2235 static struct hda_verb ad1988_capture_init_verbs[] = {
2236 /* mute analog mix */
2237 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2238 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2239 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2240 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2241 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2242 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2243 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2244 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2245 /* select ADCs - front-mic */
2246 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2247 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2248 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2250 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2251 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2252 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2257 static struct hda_verb ad1988_spdif_init_verbs[] = {
2259 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2260 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2261 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2262 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2264 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2269 /* AD1989 has no ADC -> SPDIF route */
2270 static struct hda_verb ad1989_spdif_init_verbs[] = {
2271 /* SPDIF-1 out pin */
2272 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2273 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2274 /* SPDIF-2/HDMI out pin */
2275 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2276 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2281 * verbs for 3stack (+dig)
2283 static struct hda_verb ad1988_3stack_ch2_init[] = {
2284 /* set port-C to line-in */
2285 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2286 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2287 /* set port-E to mic-in */
2288 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2289 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2293 static struct hda_verb ad1988_3stack_ch6_init[] = {
2294 /* set port-C to surround out */
2295 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2296 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2297 /* set port-E to CLFE out */
2298 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2299 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2303 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2304 { 2, ad1988_3stack_ch2_init },
2305 { 6, ad1988_3stack_ch6_init },
2308 static struct hda_verb ad1988_3stack_init_verbs[] = {
2309 /* Front, Surround, CLFE, side DAC; unmute as default */
2310 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2311 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2312 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2313 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2314 /* Port-A front headphon path */
2315 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2316 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2317 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2318 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2319 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2320 /* Port-D line-out path */
2321 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2322 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2323 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2324 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2326 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2327 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2328 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2329 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2330 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2331 /* Port-B front mic-in path */
2332 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2333 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2334 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2335 /* Port-C line-in/surround path - 6ch mode as default */
2336 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2337 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2338 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2339 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2340 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2341 /* Port-E mic-in/CLFE path - 6ch mode as default */
2342 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2343 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2344 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2345 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2346 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2347 /* mute analog mix */
2348 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2349 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2350 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2351 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2352 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2353 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2354 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2355 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2356 /* select ADCs - front-mic */
2357 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2358 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2359 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2361 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2362 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2363 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2364 /* Analog Mix output amp */
2365 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2370 * verbs for laptop mode (+dig)
2372 static struct hda_verb ad1988_laptop_hp_on[] = {
2373 /* unmute port-A and mute port-D */
2374 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2375 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2378 static struct hda_verb ad1988_laptop_hp_off[] = {
2379 /* mute port-A and unmute port-D */
2380 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2381 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2385 #define AD1988_HP_EVENT 0x01
2387 static struct hda_verb ad1988_laptop_init_verbs[] = {
2388 /* Front, Surround, CLFE, side DAC; unmute as default */
2389 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2390 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2391 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2392 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2393 /* Port-A front headphon path */
2394 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2395 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2396 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2397 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2398 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2399 /* unsolicited event for pin-sense */
2400 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2401 /* Port-D line-out path + EAPD */
2402 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2403 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2404 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2405 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2406 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2408 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2409 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2410 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2411 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2412 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2413 /* Port-B mic-in path */
2414 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2415 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2416 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2417 /* Port-C docking station - try to output */
2418 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2419 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2420 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2421 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2422 /* mute analog mix */
2423 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2424 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2425 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2426 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2427 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2428 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2429 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2430 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2431 /* select ADCs - mic */
2432 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2433 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2434 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2436 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2437 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2438 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2439 /* Analog Mix output amp */
2440 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2444 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2446 if ((res >> 26) != AD1988_HP_EVENT)
2448 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2449 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2451 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2454 #ifdef CONFIG_SND_HDA_POWER_SAVE
2455 static struct hda_amp_list ad1988_loopbacks[] = {
2456 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2457 { 0x20, HDA_INPUT, 1 }, /* Line */
2458 { 0x20, HDA_INPUT, 4 }, /* Mic */
2459 { 0x20, HDA_INPUT, 6 }, /* CD */
2465 * Automatic parse of I/O pins from the BIOS configuration
2473 static struct snd_kcontrol_new ad1988_control_templates[] = {
2474 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2475 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2476 HDA_BIND_MUTE(NULL, 0, 0, 0),
2479 /* add dynamic controls */
2480 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2483 struct snd_kcontrol_new *knew;
2485 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2486 knew = snd_array_new(&spec->kctls);
2489 *knew = ad1988_control_templates[type];
2490 knew->name = kstrdup(name, GFP_KERNEL);
2493 knew->private_value = val;
2497 #define AD1988_PIN_CD_NID 0x18
2498 #define AD1988_PIN_BEEP_NID 0x10
2500 static hda_nid_t ad1988_mixer_nids[8] = {
2501 /* A B C D E F G H */
2502 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2505 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2507 static hda_nid_t idx_to_dac[8] = {
2508 /* A B C D E F G H */
2509 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2511 static hda_nid_t idx_to_dac_rev2[8] = {
2512 /* A B C D E F G H */
2513 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2516 return idx_to_dac_rev2[idx];
2518 return idx_to_dac[idx];
2521 static hda_nid_t ad1988_boost_nids[8] = {
2522 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2525 static int ad1988_pin_idx(hda_nid_t nid)
2527 static hda_nid_t ad1988_io_pins[8] = {
2528 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2531 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2532 if (ad1988_io_pins[i] == nid)
2534 return 0; /* should be -1 */
2537 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2539 static int loopback_idx[8] = {
2540 2, 0, 1, 3, 4, 5, 1, 4
2543 case AD1988_PIN_CD_NID:
2546 return loopback_idx[ad1988_pin_idx(nid)];
2550 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2552 static int adc_idx[8] = {
2553 0, 1, 2, 8, 4, 3, 6, 7
2556 case AD1988_PIN_CD_NID:
2559 return adc_idx[ad1988_pin_idx(nid)];
2563 /* fill in the dac_nids table from the parsed pin configuration */
2564 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2565 const struct auto_pin_cfg *cfg)
2567 struct ad198x_spec *spec = codec->spec;
2570 spec->multiout.dac_nids = spec->private_dac_nids;
2572 /* check the pins hardwired to audio widget */
2573 for (i = 0; i < cfg->line_outs; i++) {
2574 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2575 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2577 spec->multiout.num_dacs = cfg->line_outs;
2581 /* add playback controls from the parsed DAC table */
2582 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2583 const struct auto_pin_cfg *cfg)
2586 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2590 for (i = 0; i < cfg->line_outs; i++) {
2591 hda_nid_t dac = spec->multiout.dac_nids[i];
2594 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2597 err = add_control(spec, AD_CTL_WIDGET_VOL,
2598 "Center Playback Volume",
2599 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2602 err = add_control(spec, AD_CTL_WIDGET_VOL,
2603 "LFE Playback Volume",
2604 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2607 err = add_control(spec, AD_CTL_BIND_MUTE,
2608 "Center Playback Switch",
2609 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2612 err = add_control(spec, AD_CTL_BIND_MUTE,
2613 "LFE Playback Switch",
2614 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2618 sprintf(name, "%s Playback Volume", chname[i]);
2619 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2620 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2623 sprintf(name, "%s Playback Switch", chname[i]);
2624 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2625 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2633 /* add playback controls for speaker and HP outputs */
2634 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2637 struct ad198x_spec *spec = codec->spec;
2645 idx = ad1988_pin_idx(pin);
2646 nid = ad1988_idx_to_dac(codec, idx);
2647 /* check whether the corresponding DAC was already taken */
2648 for (i = 0; i < spec->autocfg.line_outs; i++) {
2649 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2650 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2654 if (i >= spec->autocfg.line_outs) {
2655 /* specify the DAC as the extra output */
2656 if (!spec->multiout.hp_nid)
2657 spec->multiout.hp_nid = nid;
2659 spec->multiout.extra_out_nid[0] = nid;
2660 /* control HP volume/switch on the output mixer amp */
2661 sprintf(name, "%s Playback Volume", pfx);
2662 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2663 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2667 nid = ad1988_mixer_nids[idx];
2668 sprintf(name, "%s Playback Switch", pfx);
2669 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2670 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2675 /* create input playback/capture controls for the given pin */
2676 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2677 const char *ctlname, int boost)
2682 sprintf(name, "%s Playback Volume", ctlname);
2683 idx = ad1988_pin_to_loopback_idx(pin);
2684 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2685 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2687 sprintf(name, "%s Playback Switch", ctlname);
2688 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2689 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2693 idx = ad1988_pin_idx(pin);
2694 bnid = ad1988_boost_nids[idx];
2696 sprintf(name, "%s Boost", ctlname);
2697 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2698 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2705 /* create playback/capture controls for input pins */
2706 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2707 const struct auto_pin_cfg *cfg)
2709 struct hda_input_mux *imux = &spec->private_imux;
2712 for (i = 0; i < AUTO_PIN_LAST; i++) {
2713 err = new_analog_input(spec, cfg->input_pins[i],
2714 auto_pin_cfg_labels[i],
2715 i <= AUTO_PIN_FRONT_MIC);
2718 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2719 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2722 imux->items[imux->num_items].label = "Mix";
2723 imux->items[imux->num_items].index = 9;
2726 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2727 "Analog Mix Playback Volume",
2728 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2730 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2731 "Analog Mix Playback Switch",
2732 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2738 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2739 hda_nid_t nid, int pin_type,
2743 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2744 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2746 case 0x11: /* port-A - DAC 04 */
2747 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2749 case 0x14: /* port-B - DAC 06 */
2750 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2752 case 0x15: /* port-C - DAC 05 */
2753 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2755 case 0x17: /* port-E - DAC 0a */
2756 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2758 case 0x13: /* mono - DAC 04 */
2759 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2764 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2766 struct ad198x_spec *spec = codec->spec;
2769 for (i = 0; i < spec->autocfg.line_outs; i++) {
2770 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2771 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2775 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2777 struct ad198x_spec *spec = codec->spec;
2780 pin = spec->autocfg.speaker_pins[0];
2781 if (pin) /* connect to front */
2782 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2783 pin = spec->autocfg.hp_pins[0];
2784 if (pin) /* connect to front */
2785 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2788 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2790 struct ad198x_spec *spec = codec->spec;
2793 for (i = 0; i < AUTO_PIN_LAST; i++) {
2794 hda_nid_t nid = spec->autocfg.input_pins[i];
2798 case 0x15: /* port-C */
2799 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2801 case 0x17: /* port-E */
2802 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2805 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2806 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2807 if (nid != AD1988_PIN_CD_NID)
2808 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2810 idx = ad1988_pin_idx(nid);
2811 if (ad1988_boost_nids[idx])
2812 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2813 AC_VERB_SET_AMP_GAIN_MUTE,
2818 /* parse the BIOS configuration and set up the alc_spec */
2819 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2820 static int ad1988_parse_auto_config(struct hda_codec *codec)
2822 struct ad198x_spec *spec = codec->spec;
2825 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2827 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2829 if (! spec->autocfg.line_outs)
2830 return 0; /* can't find valid BIOS pin config */
2831 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2832 (err = ad1988_auto_create_extra_out(codec,
2833 spec->autocfg.speaker_pins[0],
2835 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2836 "Headphone")) < 0 ||
2837 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2840 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2842 if (spec->autocfg.dig_out_pin)
2843 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2844 if (spec->autocfg.dig_in_pin)
2845 spec->dig_in_nid = AD1988_SPDIF_IN;
2847 if (spec->kctls.list)
2848 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2850 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2852 spec->input_mux = &spec->private_imux;
2857 /* init callback for auto-configuration model -- overriding the default init */
2858 static int ad1988_auto_init(struct hda_codec *codec)
2861 ad1988_auto_init_multi_out(codec);
2862 ad1988_auto_init_extra_out(codec);
2863 ad1988_auto_init_analog_input(codec);
2871 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2872 [AD1988_6STACK] = "6stack",
2873 [AD1988_6STACK_DIG] = "6stack-dig",
2874 [AD1988_3STACK] = "3stack",
2875 [AD1988_3STACK_DIG] = "3stack-dig",
2876 [AD1988_LAPTOP] = "laptop",
2877 [AD1988_LAPTOP_DIG] = "laptop-dig",
2878 [AD1988_AUTO] = "auto",
2881 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2882 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2883 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2884 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
2885 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
2889 static int patch_ad1988(struct hda_codec *codec)
2891 struct ad198x_spec *spec;
2894 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2901 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2903 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2904 ad1988_models, ad1988_cfg_tbl);
2905 if (board_config < 0) {
2906 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2907 board_config = AD1988_AUTO;
2910 if (board_config == AD1988_AUTO) {
2911 /* automatic parse from the BIOS config */
2912 int err = ad1988_parse_auto_config(codec);
2917 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2918 board_config = AD1988_6STACK;
2922 switch (board_config) {
2924 case AD1988_6STACK_DIG:
2925 spec->multiout.max_channels = 8;
2926 spec->multiout.num_dacs = 4;
2928 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2930 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
2931 spec->input_mux = &ad1988_6stack_capture_source;
2932 spec->num_mixers = 2;
2934 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2936 spec->mixers[0] = ad1988_6stack_mixers1;
2937 spec->mixers[1] = ad1988_6stack_mixers2;
2938 spec->num_init_verbs = 1;
2939 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2940 if (board_config == AD1988_6STACK_DIG) {
2941 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2942 spec->dig_in_nid = AD1988_SPDIF_IN;
2946 case AD1988_3STACK_DIG:
2947 spec->multiout.max_channels = 6;
2948 spec->multiout.num_dacs = 3;
2950 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2952 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2953 spec->input_mux = &ad1988_6stack_capture_source;
2954 spec->channel_mode = ad1988_3stack_modes;
2955 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
2956 spec->num_mixers = 2;
2958 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
2960 spec->mixers[0] = ad1988_3stack_mixers1;
2961 spec->mixers[1] = ad1988_3stack_mixers2;
2962 spec->num_init_verbs = 1;
2963 spec->init_verbs[0] = ad1988_3stack_init_verbs;
2964 if (board_config == AD1988_3STACK_DIG)
2965 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2968 case AD1988_LAPTOP_DIG:
2969 spec->multiout.max_channels = 2;
2970 spec->multiout.num_dacs = 1;
2971 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2972 spec->input_mux = &ad1988_laptop_capture_source;
2973 spec->num_mixers = 1;
2974 spec->mixers[0] = ad1988_laptop_mixers;
2975 spec->num_init_verbs = 1;
2976 spec->init_verbs[0] = ad1988_laptop_init_verbs;
2977 if (board_config == AD1988_LAPTOP_DIG)
2978 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2982 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
2983 spec->adc_nids = ad1988_adc_nids;
2984 spec->capsrc_nids = ad1988_capsrc_nids;
2985 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
2986 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
2987 if (spec->multiout.dig_out_nid) {
2988 if (codec->vendor_id >= 0x11d4989a) {
2989 spec->mixers[spec->num_mixers++] =
2990 ad1989_spdif_out_mixers;
2991 spec->init_verbs[spec->num_init_verbs++] =
2992 ad1989_spdif_init_verbs;
2993 codec->slave_dig_outs = ad1989b_slave_dig_outs;
2995 spec->mixers[spec->num_mixers++] =
2996 ad1988_spdif_out_mixers;
2997 spec->init_verbs[spec->num_init_verbs++] =
2998 ad1988_spdif_init_verbs;
3001 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3002 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3004 codec->patch_ops = ad198x_patch_ops;
3005 switch (board_config) {
3007 codec->patch_ops.init = ad1988_auto_init;
3010 case AD1988_LAPTOP_DIG:
3011 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3014 #ifdef CONFIG_SND_HDA_POWER_SAVE
3015 spec->loopback.amplist = ad1988_loopbacks;
3017 spec->vmaster_nid = 0x04;
3026 * port-B - front line/mic-in
3027 * port-E - aux in/out
3028 * port-F - aux in/out
3029 * port-C - rear line/mic-in
3030 * port-D - rear line/hp-out
3031 * port-A - front line/hp-out
3033 * AD1984 = AD1884 + two digital mic-ins
3036 * For simplicity, we share the single DAC for both HP and line-outs
3037 * right now. The inidividual playbacks could be easily implemented,
3038 * but no build-up framework is given, so far.
3041 static hda_nid_t ad1884_dac_nids[1] = {
3045 static hda_nid_t ad1884_adc_nids[2] = {
3049 static hda_nid_t ad1884_capsrc_nids[2] = {
3053 #define AD1884_SPDIF_OUT 0x02
3055 static struct hda_input_mux ad1884_capture_source = {
3058 { "Front Mic", 0x0 },
3065 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3066 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3067 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3068 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3069 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3070 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3071 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3072 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3073 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3074 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3075 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3076 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3077 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3079 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3080 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3081 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
3082 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3084 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3085 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3086 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3087 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3088 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3089 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3091 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3092 /* The multiple "Capture Source" controls confuse alsamixer
3093 * So call somewhat different..
3095 /* .name = "Capture Source", */
3096 .name = "Input Source",
3098 .info = ad198x_mux_enum_info,
3099 .get = ad198x_mux_enum_get,
3100 .put = ad198x_mux_enum_put,
3102 /* SPDIF controls */
3103 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3105 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3106 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3107 /* identical with ad1983 */
3108 .info = ad1983_spdif_route_info,
3109 .get = ad1983_spdif_route_get,
3110 .put = ad1983_spdif_route_put,
3115 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3116 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3117 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3118 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3120 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3126 * initialization verbs
3128 static struct hda_verb ad1884_init_verbs[] = {
3129 /* DACs; mute as default */
3130 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3131 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3132 /* Port-A (HP) mixer */
3133 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3134 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3136 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3137 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3138 /* HP selector - select DAC2 */
3139 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3140 /* Port-D (Line-out) mixer */
3141 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3142 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3144 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3145 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3146 /* Mono-out mixer */
3147 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3148 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3150 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3151 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3153 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3154 /* Port-B (front mic) pin */
3155 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3156 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3157 /* Port-C (rear mic) pin */
3158 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3159 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3160 /* Analog mixer; mute as default */
3161 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3162 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3163 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3164 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3165 /* Analog Mix output amp */
3166 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3167 /* SPDIF output selector */
3168 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3169 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3173 #ifdef CONFIG_SND_HDA_POWER_SAVE
3174 static struct hda_amp_list ad1884_loopbacks[] = {
3175 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3176 { 0x20, HDA_INPUT, 1 }, /* Mic */
3177 { 0x20, HDA_INPUT, 2 }, /* CD */
3178 { 0x20, HDA_INPUT, 4 }, /* Docking */
3183 static const char *ad1884_slave_vols[] = {
3184 "PCM Playback Volume",
3185 "Mic Playback Volume",
3186 "Mono Playback Volume",
3187 "Front Mic Playback Volume",
3188 "Mic Playback Volume",
3189 "CD Playback Volume",
3190 "Internal Mic Playback Volume",
3191 "Docking Mic Playback Volume"
3192 "Beep Playback Volume",
3193 "IEC958 Playback Volume",
3197 static int patch_ad1884(struct hda_codec *codec)
3199 struct ad198x_spec *spec;
3201 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3207 spec->multiout.max_channels = 2;
3208 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3209 spec->multiout.dac_nids = ad1884_dac_nids;
3210 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3211 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3212 spec->adc_nids = ad1884_adc_nids;
3213 spec->capsrc_nids = ad1884_capsrc_nids;
3214 spec->input_mux = &ad1884_capture_source;
3215 spec->num_mixers = 1;
3216 spec->mixers[0] = ad1884_base_mixers;
3217 spec->num_init_verbs = 1;
3218 spec->init_verbs[0] = ad1884_init_verbs;
3219 spec->spdif_route = 0;
3220 #ifdef CONFIG_SND_HDA_POWER_SAVE
3221 spec->loopback.amplist = ad1884_loopbacks;
3223 spec->vmaster_nid = 0x04;
3224 /* we need to cover all playback volumes */
3225 spec->slave_vols = ad1884_slave_vols;
3227 codec->patch_ops = ad198x_patch_ops;
3233 * Lenovo Thinkpad T61/X61
3235 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3239 { "Internal Mic", 0x1 },
3241 { "Docking-Station", 0x4 },
3247 * Dell Precision T3400
3249 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3252 { "Front Mic", 0x0 },
3259 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3260 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3261 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3262 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3263 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3264 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3265 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3266 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3267 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3268 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3269 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3270 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3271 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3272 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3273 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3274 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3275 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3276 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3277 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3278 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3280 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3281 /* The multiple "Capture Source" controls confuse alsamixer
3282 * So call somewhat different..
3284 /* .name = "Capture Source", */
3285 .name = "Input Source",
3287 .info = ad198x_mux_enum_info,
3288 .get = ad198x_mux_enum_get,
3289 .put = ad198x_mux_enum_put,
3291 /* SPDIF controls */
3292 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3294 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3295 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3296 /* identical with ad1983 */
3297 .info = ad1983_spdif_route_info,
3298 .get = ad1983_spdif_route_get,
3299 .put = ad1983_spdif_route_put,
3304 /* additional verbs */
3305 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3306 /* Port-E (docking station mic) pin */
3307 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3308 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3309 /* docking mic boost */
3310 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3311 /* Analog mixer - docking mic; mute as default */
3312 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3313 /* enable EAPD bit */
3314 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3319 * Dell Precision T3400
3321 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3322 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3323 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3324 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3325 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3326 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3327 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3328 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3329 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3330 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3332 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3333 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3335 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3336 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3337 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3338 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3339 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3340 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3342 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3343 /* The multiple "Capture Source" controls confuse alsamixer
3344 * So call somewhat different..
3346 /* .name = "Capture Source", */
3347 .name = "Input Source",
3349 .info = ad198x_mux_enum_info,
3350 .get = ad198x_mux_enum_get,
3351 .put = ad198x_mux_enum_put,
3356 /* Digial MIC ADC NID 0x05 + 0x06 */
3357 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3358 struct hda_codec *codec,
3359 unsigned int stream_tag,
3360 unsigned int format,
3361 struct snd_pcm_substream *substream)
3363 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3364 stream_tag, 0, format);
3368 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3369 struct hda_codec *codec,
3370 struct snd_pcm_substream *substream)
3372 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3376 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3382 .prepare = ad1984_pcm_dmic_prepare,
3383 .cleanup = ad1984_pcm_dmic_cleanup
3387 static int ad1984_build_pcms(struct hda_codec *codec)
3389 struct ad198x_spec *spec = codec->spec;
3390 struct hda_pcm *info;
3393 err = ad198x_build_pcms(codec);
3397 info = spec->pcm_rec + codec->num_pcms;
3399 info->name = "AD1984 Digital Mic";
3400 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3408 AD1984_DELL_DESKTOP,
3412 static const char *ad1984_models[AD1984_MODELS] = {
3413 [AD1984_BASIC] = "basic",
3414 [AD1984_THINKPAD] = "thinkpad",
3415 [AD1984_DELL_DESKTOP] = "dell_desktop",
3418 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3419 /* Lenovo Thinkpad T61/X61 */
3420 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
3421 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3425 static int patch_ad1984(struct hda_codec *codec)
3427 struct ad198x_spec *spec;
3428 int board_config, err;
3430 err = patch_ad1884(codec);
3434 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3435 ad1984_models, ad1984_cfg_tbl);
3436 switch (board_config) {
3438 /* additional digital mics */
3439 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3440 codec->patch_ops.build_pcms = ad1984_build_pcms;
3442 case AD1984_THINKPAD:
3443 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3444 spec->input_mux = &ad1984_thinkpad_capture_source;
3445 spec->mixers[0] = ad1984_thinkpad_mixers;
3446 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3448 case AD1984_DELL_DESKTOP:
3449 spec->multiout.dig_out_nid = 0;
3450 spec->input_mux = &ad1984_dell_desktop_capture_source;
3451 spec->mixers[0] = ad1984_dell_desktop_mixers;
3459 * AD1883 / AD1884A / AD1984A / AD1984B
3461 * port-B (0x14) - front mic-in
3462 * port-E (0x1c) - rear mic-in
3463 * port-F (0x16) - CD / ext out
3464 * port-C (0x15) - rear line-in
3465 * port-D (0x12) - rear line-out
3466 * port-A (0x11) - front hp-out
3468 * AD1984A = AD1884A + digital-mic
3469 * AD1883 = equivalent with AD1984A
3470 * AD1984B = AD1984A + extra SPDIF-out
3473 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3476 static hda_nid_t ad1884a_dac_nids[1] = {
3480 #define ad1884a_adc_nids ad1884_adc_nids
3481 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3483 #define AD1884A_SPDIF_OUT 0x02
3485 static struct hda_input_mux ad1884a_capture_source = {
3488 { "Front Mic", 0x0 },
3496 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3497 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3498 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3499 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3500 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3501 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3502 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3503 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3504 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3505 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3506 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3507 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3508 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3509 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3510 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3511 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3512 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3513 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3514 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3515 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3516 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3517 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3518 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3519 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3520 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3521 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3524 /* The multiple "Capture Source" controls confuse alsamixer
3525 * So call somewhat different..
3527 /* .name = "Capture Source", */
3528 .name = "Input Source",
3530 .info = ad198x_mux_enum_info,
3531 .get = ad198x_mux_enum_get,
3532 .put = ad198x_mux_enum_put,
3534 /* SPDIF controls */
3535 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3537 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3538 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3539 /* identical with ad1983 */
3540 .info = ad1983_spdif_route_info,
3541 .get = ad1983_spdif_route_get,
3542 .put = ad1983_spdif_route_put,
3548 * initialization verbs
3550 static struct hda_verb ad1884a_init_verbs[] = {
3551 /* DACs; unmute as default */
3552 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3553 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3554 /* Port-A (HP) mixer - route only from analog mixer */
3555 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3556 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3558 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3559 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3560 /* Port-D (Line-out) mixer - route only from analog mixer */
3561 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3562 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3564 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3565 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3566 /* Mono-out mixer - route only from analog mixer */
3567 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3568 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3570 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3571 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3572 /* Port-B (front mic) pin */
3573 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3574 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3575 /* Port-C (rear line-in) pin */
3576 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3577 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3578 /* Port-E (rear mic) pin */
3579 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3580 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3581 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3582 /* Port-F (CD) pin */
3583 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3584 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3585 /* Analog mixer; mute as default */
3586 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3587 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3588 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3589 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3590 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3591 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3592 /* Analog Mix output amp */
3593 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3594 /* capture sources */
3595 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3596 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3597 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3598 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3599 /* SPDIF output amp */
3600 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3604 #ifdef CONFIG_SND_HDA_POWER_SAVE
3605 static struct hda_amp_list ad1884a_loopbacks[] = {
3606 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3607 { 0x20, HDA_INPUT, 1 }, /* Mic */
3608 { 0x20, HDA_INPUT, 2 }, /* CD */
3609 { 0x20, HDA_INPUT, 4 }, /* Docking */
3617 * Port A: Headphone jack
3619 * Port C: Internal MIC
3620 * Port D: Dock Line Out (if enabled)
3621 * Port E: Dock Line In (if enabled)
3622 * Port F: Internal speakers
3625 static struct hda_input_mux ad1884a_laptop_capture_source = {
3628 { "Mic", 0x0 }, /* port-B */
3629 { "Internal Mic", 0x1 }, /* port-C */
3630 { "Dock Mic", 0x4 }, /* port-E */
3635 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3636 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3637 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3638 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3639 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3640 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3641 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3642 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3643 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3644 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3645 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3646 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3647 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3648 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3649 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3650 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3651 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3652 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3653 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3654 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3655 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3658 /* The multiple "Capture Source" controls confuse alsamixer
3659 * So call somewhat different..
3661 /* .name = "Capture Source", */
3662 .name = "Input Source",
3664 .info = ad198x_mux_enum_info,
3665 .get = ad198x_mux_enum_get,
3666 .put = ad198x_mux_enum_put,
3671 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3672 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3673 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3674 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3675 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3676 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3677 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3678 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3679 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3680 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3681 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3685 /* mute internal speaker if HP is plugged */
3686 static void ad1884a_hp_automute(struct hda_codec *codec)
3688 unsigned int present;
3690 present = snd_hda_codec_read(codec, 0x11, 0,
3691 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3692 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3693 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3694 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3695 present ? 0x00 : 0x02);
3698 /* switch to external mic if plugged */
3699 static void ad1884a_hp_automic(struct hda_codec *codec)
3701 unsigned int present;
3703 present = snd_hda_codec_read(codec, 0x14, 0,
3704 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3705 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3709 #define AD1884A_HP_EVENT 0x37
3710 #define AD1884A_MIC_EVENT 0x36
3712 /* unsolicited event for HP jack sensing */
3713 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3715 switch (res >> 26) {
3716 case AD1884A_HP_EVENT:
3717 ad1884a_hp_automute(codec);
3719 case AD1884A_MIC_EVENT:
3720 ad1884a_hp_automic(codec);
3725 /* initialize jack-sensing, too */
3726 static int ad1884a_hp_init(struct hda_codec *codec)
3729 ad1884a_hp_automute(codec);
3730 ad1884a_hp_automic(codec);
3734 /* additional verbs for laptop model */
3735 static struct hda_verb ad1884a_laptop_verbs[] = {
3736 /* Port-A (HP) pin - always unmuted */
3737 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3738 /* Port-F (int speaker) mixer - route only from analog mixer */
3739 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3740 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3742 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3743 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3744 /* Port-C pin - internal mic-in */
3745 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3746 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3747 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3749 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3750 /* unsolicited event for pin-sense */
3751 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3752 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3761 * 0x17 - built-in mic
3764 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3766 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3768 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3770 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3771 /* unsolicited event for pin-sense */
3772 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3773 /* internal mic - dmic */
3774 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3775 /* set magic COEFs for dmic */
3776 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3777 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
3781 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3782 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3783 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3784 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3785 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3786 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3787 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3788 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3789 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3790 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3791 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3792 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3793 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3795 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3796 .name = "Capture Source",
3797 .info = ad198x_mux_enum_info,
3798 .get = ad198x_mux_enum_get,
3799 .put = ad198x_mux_enum_put,
3804 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
3808 { "Internal Mic", 0x5 },
3813 /* mute internal speaker if HP is plugged */
3814 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
3816 unsigned int present;
3818 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
3819 & AC_PINSENSE_PRESENCE;
3820 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
3821 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3824 /* unsolicited event for HP jack sensing */
3825 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
3828 if ((res >> 26) != AD1884A_HP_EVENT)
3830 ad1984a_thinkpad_automute(codec);
3833 /* initialize jack-sensing, too */
3834 static int ad1984a_thinkpad_init(struct hda_codec *codec)
3837 ad1984a_thinkpad_automute(codec);
3852 static const char *ad1884a_models[AD1884A_MODELS] = {
3853 [AD1884A_DESKTOP] = "desktop",
3854 [AD1884A_LAPTOP] = "laptop",
3855 [AD1884A_MOBILE] = "mobile",
3856 [AD1884A_THINKPAD] = "thinkpad",
3859 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3860 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
3861 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
3862 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
3866 static int patch_ad1884a(struct hda_codec *codec)
3868 struct ad198x_spec *spec;
3871 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3877 spec->multiout.max_channels = 2;
3878 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3879 spec->multiout.dac_nids = ad1884a_dac_nids;
3880 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3881 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3882 spec->adc_nids = ad1884a_adc_nids;
3883 spec->capsrc_nids = ad1884a_capsrc_nids;
3884 spec->input_mux = &ad1884a_capture_source;
3885 spec->num_mixers = 1;
3886 spec->mixers[0] = ad1884a_base_mixers;
3887 spec->num_init_verbs = 1;
3888 spec->init_verbs[0] = ad1884a_init_verbs;
3889 spec->spdif_route = 0;
3890 #ifdef CONFIG_SND_HDA_POWER_SAVE
3891 spec->loopback.amplist = ad1884a_loopbacks;
3893 codec->patch_ops = ad198x_patch_ops;
3895 /* override some parameters */
3896 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
3899 switch (board_config) {
3900 case AD1884A_LAPTOP:
3901 spec->mixers[0] = ad1884a_laptop_mixers;
3902 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3903 spec->multiout.dig_out_nid = 0;
3904 spec->input_mux = &ad1884a_laptop_capture_source;
3905 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3906 codec->patch_ops.init = ad1884a_hp_init;
3908 case AD1884A_MOBILE:
3909 spec->mixers[0] = ad1884a_mobile_mixers;
3910 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3911 spec->multiout.dig_out_nid = 0;
3912 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3913 codec->patch_ops.init = ad1884a_hp_init;
3915 case AD1884A_THINKPAD:
3916 spec->mixers[0] = ad1984a_thinkpad_mixers;
3917 spec->init_verbs[spec->num_init_verbs++] =
3918 ad1984a_thinkpad_verbs;
3919 spec->multiout.dig_out_nid = 0;
3920 spec->input_mux = &ad1984a_thinkpad_capture_source;
3921 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
3922 codec->patch_ops.init = ad1984a_thinkpad_init;
3933 * port-A - front hp-out
3934 * port-B - front mic-in
3935 * port-C - rear line-in, shared surr-out (3stack)
3936 * port-D - rear line-out
3937 * port-E - rear mic-in, shared clfe-out (3stack)
3938 * port-F - rear surr-out (6stack)
3939 * port-G - rear clfe-out (6stack)
3942 static hda_nid_t ad1882_dac_nids[3] = {
3946 static hda_nid_t ad1882_adc_nids[2] = {
3950 static hda_nid_t ad1882_capsrc_nids[2] = {
3954 #define AD1882_SPDIF_OUT 0x02
3956 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
3957 static struct hda_input_mux ad1882_capture_source = {
3960 { "Front Mic", 0x1 },
3968 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
3969 static struct hda_input_mux ad1882a_capture_source = {
3972 { "Front Mic", 0x1 },
3975 { "Digital Mic", 0x06 },
3980 static struct snd_kcontrol_new ad1882_base_mixers[] = {
3981 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3982 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
3983 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
3984 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
3985 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3986 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3987 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3988 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3990 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
3991 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
3992 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
3993 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3994 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3995 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3996 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3998 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3999 /* The multiple "Capture Source" controls confuse alsamixer
4000 * So call somewhat different..
4002 /* .name = "Capture Source", */
4003 .name = "Input Source",
4005 .info = ad198x_mux_enum_info,
4006 .get = ad198x_mux_enum_get,
4007 .put = ad198x_mux_enum_put,
4009 /* SPDIF controls */
4010 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4012 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4013 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4014 /* identical with ad1983 */
4015 .info = ad1983_spdif_route_info,
4016 .get = ad1983_spdif_route_get,
4017 .put = ad1983_spdif_route_put,
4022 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4023 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4024 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4025 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4026 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4027 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4028 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4029 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4030 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4031 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4032 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4036 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4037 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4038 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4039 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4040 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4041 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4042 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4043 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4044 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4045 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
4046 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
4047 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4051 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4052 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4053 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4054 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4056 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4057 .name = "Channel Mode",
4058 .info = ad198x_ch_mode_info,
4059 .get = ad198x_ch_mode_get,
4060 .put = ad198x_ch_mode_put,
4065 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4066 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4067 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4068 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4072 static struct hda_verb ad1882_ch2_init[] = {
4073 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4074 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4075 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4076 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4077 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4078 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4082 static struct hda_verb ad1882_ch4_init[] = {
4083 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4084 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4085 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4086 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4087 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4088 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4092 static struct hda_verb ad1882_ch6_init[] = {
4093 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4094 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4095 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4096 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4097 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4098 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4102 static struct hda_channel_mode ad1882_modes[3] = {
4103 { 2, ad1882_ch2_init },
4104 { 4, ad1882_ch4_init },
4105 { 6, ad1882_ch6_init },
4109 * initialization verbs
4111 static struct hda_verb ad1882_init_verbs[] = {
4112 /* DACs; mute as default */
4113 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4114 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4115 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4116 /* Port-A (HP) mixer */
4117 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4118 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4120 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4121 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4122 /* HP selector - select DAC2 */
4123 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4124 /* Port-D (Line-out) mixer */
4125 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4126 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4128 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4129 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4130 /* Mono-out mixer */
4131 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4132 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4134 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4135 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4136 /* Port-B (front mic) pin */
4137 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4138 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4139 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4140 /* Port-C (line-in) pin */
4141 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4142 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4143 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4144 /* Port-C mixer - mute as input */
4145 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4146 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4147 /* Port-E (mic-in) pin */
4148 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4149 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4150 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4151 /* Port-E mixer - mute as input */
4152 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4153 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4154 /* Port-F (surround) */
4155 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4156 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4158 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4159 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4160 /* Analog mixer; mute as default */
4161 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4162 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4163 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4164 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4165 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4166 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4167 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4168 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4169 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4170 /* Analog Mix output amp */
4171 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4172 /* SPDIF output selector */
4173 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4174 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4175 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4179 #ifdef CONFIG_SND_HDA_POWER_SAVE
4180 static struct hda_amp_list ad1882_loopbacks[] = {
4181 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4182 { 0x20, HDA_INPUT, 1 }, /* Mic */
4183 { 0x20, HDA_INPUT, 4 }, /* Line */
4184 { 0x20, HDA_INPUT, 6 }, /* CD */
4196 static const char *ad1882_models[AD1986A_MODELS] = {
4197 [AD1882_3STACK] = "3stack",
4198 [AD1882_6STACK] = "6stack",
4202 static int patch_ad1882(struct hda_codec *codec)
4204 struct ad198x_spec *spec;
4207 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4213 spec->multiout.max_channels = 6;
4214 spec->multiout.num_dacs = 3;
4215 spec->multiout.dac_nids = ad1882_dac_nids;
4216 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4217 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4218 spec->adc_nids = ad1882_adc_nids;
4219 spec->capsrc_nids = ad1882_capsrc_nids;
4220 if (codec->vendor_id == 0x11d1882)
4221 spec->input_mux = &ad1882_capture_source;
4223 spec->input_mux = &ad1882a_capture_source;
4224 spec->num_mixers = 2;
4225 spec->mixers[0] = ad1882_base_mixers;
4226 if (codec->vendor_id == 0x11d1882)
4227 spec->mixers[1] = ad1882_loopback_mixers;
4229 spec->mixers[1] = ad1882a_loopback_mixers;
4230 spec->num_init_verbs = 1;
4231 spec->init_verbs[0] = ad1882_init_verbs;
4232 spec->spdif_route = 0;
4233 #ifdef CONFIG_SND_HDA_POWER_SAVE
4234 spec->loopback.amplist = ad1882_loopbacks;
4236 spec->vmaster_nid = 0x04;
4238 codec->patch_ops = ad198x_patch_ops;
4240 /* override some parameters */
4241 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4242 ad1882_models, NULL);
4243 switch (board_config) {
4246 spec->num_mixers = 3;
4247 spec->mixers[2] = ad1882_3stack_mixers;
4248 spec->channel_mode = ad1882_modes;
4249 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4250 spec->need_dac_fix = 1;
4251 spec->multiout.max_channels = 2;
4252 spec->multiout.num_dacs = 1;
4255 spec->num_mixers = 3;
4256 spec->mixers[2] = ad1882_6stack_mixers;
4266 struct hda_codec_preset snd_hda_preset_analog[] = {
4267 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4268 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4269 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4270 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4271 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4272 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4273 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4274 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4275 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4276 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4277 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4278 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4279 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4280 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4281 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },