2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 struct snd_kcontrol_new *mixers[5];
35 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb *init_verbs[5]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs;
42 struct hda_multi_out multiout; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd;
47 unsigned int need_dac_fix;
50 unsigned int num_adc_nids;
52 hda_nid_t dig_in_nid; /* digital-in NID; optional */
55 const struct hda_input_mux *input_mux;
56 hda_nid_t *capsrc_nids;
57 unsigned int cur_mux[3];
60 const struct hda_channel_mode *channel_mode;
64 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
66 unsigned int spdif_route;
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg;
70 struct snd_array kctls;
71 struct hda_input_mux private_imux;
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
74 unsigned int jack_present :1;
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 /* additional beep mixers; the actual parameters are overwritten at build */
159 static struct snd_kcontrol_new ad_beep_mixer[] = {
160 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
161 HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT),
165 #define set_beep_amp(spec, nid, idx, dir) \
166 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
168 static int ad198x_build_controls(struct hda_codec *codec)
170 struct ad198x_spec *spec = codec->spec;
174 for (i = 0; i < spec->num_mixers; i++) {
175 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
179 if (spec->multiout.dig_out_nid) {
180 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
183 err = snd_hda_create_spdif_share_sw(codec,
187 spec->multiout.share_spdif = 1;
189 if (spec->dig_in_nid) {
190 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
195 /* create beep controls if needed */
196 if (spec->beep_amp) {
197 struct snd_kcontrol_new *knew;
198 for (knew = ad_beep_mixer; knew->name; knew++) {
199 struct snd_kcontrol *kctl;
200 kctl = snd_ctl_new1(knew, codec);
203 kctl->private_value = spec->beep_amp;
204 err = snd_hda_ctl_add(codec, kctl);
210 /* if we have no master control, let's create it */
211 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
212 unsigned int vmaster_tlv[4];
213 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
214 HDA_OUTPUT, vmaster_tlv);
215 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
218 spec->slave_vols : ad_slave_vols));
222 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
223 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
226 spec->slave_sws : ad_slave_sws));
231 ad198x_free_kctls(codec); /* no longer needed */
235 #ifdef CONFIG_SND_HDA_POWER_SAVE
236 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
238 struct ad198x_spec *spec = codec->spec;
239 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
244 * Analog playback callbacks
246 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
247 struct hda_codec *codec,
248 struct snd_pcm_substream *substream)
250 struct ad198x_spec *spec = codec->spec;
251 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
255 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
256 struct hda_codec *codec,
257 unsigned int stream_tag,
259 struct snd_pcm_substream *substream)
261 struct ad198x_spec *spec = codec->spec;
262 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
266 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
267 struct hda_codec *codec,
268 struct snd_pcm_substream *substream)
270 struct ad198x_spec *spec = codec->spec;
271 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
277 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
278 struct hda_codec *codec,
279 struct snd_pcm_substream *substream)
281 struct ad198x_spec *spec = codec->spec;
282 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
285 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
286 struct hda_codec *codec,
287 struct snd_pcm_substream *substream)
289 struct ad198x_spec *spec = codec->spec;
290 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
293 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
294 struct hda_codec *codec,
295 unsigned int stream_tag,
297 struct snd_pcm_substream *substream)
299 struct ad198x_spec *spec = codec->spec;
300 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
304 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
305 struct hda_codec *codec,
306 struct snd_pcm_substream *substream)
308 struct ad198x_spec *spec = codec->spec;
309 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
315 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
316 struct hda_codec *codec,
317 unsigned int stream_tag,
319 struct snd_pcm_substream *substream)
321 struct ad198x_spec *spec = codec->spec;
322 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
323 stream_tag, 0, format);
327 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
328 struct hda_codec *codec,
329 struct snd_pcm_substream *substream)
331 struct ad198x_spec *spec = codec->spec;
332 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
339 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
342 .channels_max = 6, /* changed later */
343 .nid = 0, /* fill later */
345 .open = ad198x_playback_pcm_open,
346 .prepare = ad198x_playback_pcm_prepare,
347 .cleanup = ad198x_playback_pcm_cleanup
351 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
355 .nid = 0, /* fill later */
357 .prepare = ad198x_capture_pcm_prepare,
358 .cleanup = ad198x_capture_pcm_cleanup
362 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
366 .nid = 0, /* fill later */
368 .open = ad198x_dig_playback_pcm_open,
369 .close = ad198x_dig_playback_pcm_close,
370 .prepare = ad198x_dig_playback_pcm_prepare,
371 .cleanup = ad198x_dig_playback_pcm_cleanup
375 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
379 /* NID is set in alc_build_pcms */
382 static int ad198x_build_pcms(struct hda_codec *codec)
384 struct ad198x_spec *spec = codec->spec;
385 struct hda_pcm *info = spec->pcm_rec;
388 codec->pcm_info = info;
390 info->name = "AD198x Analog";
391 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
392 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
393 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
394 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
395 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
396 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
398 if (spec->multiout.dig_out_nid) {
401 info->name = "AD198x Digital";
402 info->pcm_type = HDA_PCM_TYPE_SPDIF;
403 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
404 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
405 if (spec->dig_in_nid) {
406 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
407 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
414 static void ad198x_free_kctls(struct hda_codec *codec)
416 struct ad198x_spec *spec = codec->spec;
418 if (spec->kctls.list) {
419 struct snd_kcontrol_new *kctl = spec->kctls.list;
421 for (i = 0; i < spec->kctls.used; i++)
424 snd_array_free(&spec->kctls);
427 static void ad198x_free(struct hda_codec *codec)
429 struct ad198x_spec *spec = codec->spec;
434 ad198x_free_kctls(codec);
436 snd_hda_detach_beep_device(codec);
439 static struct hda_codec_ops ad198x_patch_ops = {
440 .build_controls = ad198x_build_controls,
441 .build_pcms = ad198x_build_pcms,
444 #ifdef CONFIG_SND_HDA_POWER_SAVE
445 .check_power_status = ad198x_check_power_status,
452 * the private value = nid | (invert << 8)
454 #define ad198x_eapd_info snd_ctl_boolean_mono_info
456 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
457 struct snd_ctl_elem_value *ucontrol)
459 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
460 struct ad198x_spec *spec = codec->spec;
461 int invert = (kcontrol->private_value >> 8) & 1;
463 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
465 ucontrol->value.integer.value[0] = spec->cur_eapd;
469 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
472 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
473 struct ad198x_spec *spec = codec->spec;
474 int invert = (kcontrol->private_value >> 8) & 1;
475 hda_nid_t nid = kcontrol->private_value & 0xff;
477 eapd = !!ucontrol->value.integer.value[0];
480 if (eapd == spec->cur_eapd)
482 spec->cur_eapd = eapd;
483 snd_hda_codec_write_cache(codec, nid,
484 0, AC_VERB_SET_EAPD_BTLENABLE,
489 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
490 struct snd_ctl_elem_info *uinfo);
491 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *ucontrol);
493 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
494 struct snd_ctl_elem_value *ucontrol);
501 #define AD1986A_SPDIF_OUT 0x02
502 #define AD1986A_FRONT_DAC 0x03
503 #define AD1986A_SURR_DAC 0x04
504 #define AD1986A_CLFE_DAC 0x05
505 #define AD1986A_ADC 0x06
507 static hda_nid_t ad1986a_dac_nids[3] = {
508 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
510 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
511 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
513 static struct hda_input_mux ad1986a_capture_source = {
527 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
528 .ops = &snd_hda_bind_vol,
530 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
531 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
532 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
537 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
538 .ops = &snd_hda_bind_sw,
540 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
541 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
542 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
550 static struct snd_kcontrol_new ad1986a_mixers[] = {
552 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
554 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
555 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
556 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
557 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
558 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
559 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
560 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
561 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
562 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
563 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
564 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
565 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
566 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
567 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
568 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
569 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
570 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
571 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
572 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
573 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
574 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
575 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
576 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
577 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
578 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
581 .name = "Capture Source",
582 .info = ad198x_mux_enum_info,
583 .get = ad198x_mux_enum_get,
584 .put = ad198x_mux_enum_put,
586 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
590 /* additional mixers for 3stack mode */
591 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
593 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
594 .name = "Channel Mode",
595 .info = ad198x_ch_mode_info,
596 .get = ad198x_ch_mode_get,
597 .put = ad198x_ch_mode_put,
602 /* laptop model - 2ch only */
603 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
605 /* master controls both pins 0x1a and 0x1b */
606 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
607 .ops = &snd_hda_bind_vol,
609 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
610 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
615 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
616 .ops = &snd_hda_bind_sw,
618 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
619 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
624 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
625 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
626 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
627 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
628 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
629 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
630 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
631 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
632 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
633 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
634 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
635 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
636 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
637 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
639 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
640 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
641 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
642 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
644 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
645 .name = "Capture Source",
646 .info = ad198x_mux_enum_info,
647 .get = ad198x_mux_enum_get,
648 .put = ad198x_mux_enum_put,
653 /* laptop-eapd model - 2ch only */
655 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
659 { "Internal Mic", 0x4 },
664 static struct hda_input_mux ad1986a_automic_capture_source = {
672 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
673 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
674 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
675 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
676 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
677 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
678 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
679 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
680 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
681 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
682 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
683 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
685 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
686 .name = "Capture Source",
687 .info = ad198x_mux_enum_info,
688 .get = ad198x_mux_enum_get,
689 .put = ad198x_mux_enum_put,
692 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
693 .name = "External Amplifier",
694 .info = ad198x_eapd_info,
695 .get = ad198x_eapd_get,
696 .put = ad198x_eapd_put,
697 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
702 static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
703 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
704 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
705 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
706 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
707 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
708 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
709 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
710 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
711 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
713 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
714 .name = "Capture Source",
715 .info = ad198x_mux_enum_info,
716 .get = ad198x_mux_enum_get,
717 .put = ad198x_mux_enum_put,
720 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
721 .name = "External Amplifier",
722 .info = ad198x_eapd_info,
723 .get = ad198x_eapd_get,
724 .put = ad198x_eapd_put,
725 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
730 /* re-connect the mic boost input according to the jack sensing */
731 static void ad1986a_automic(struct hda_codec *codec)
733 unsigned int present;
734 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
735 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
736 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
737 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
740 #define AD1986A_MIC_EVENT 0x36
742 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
745 if ((res >> 26) != AD1986A_MIC_EVENT)
747 ad1986a_automic(codec);
750 static int ad1986a_automic_init(struct hda_codec *codec)
753 ad1986a_automic(codec);
757 /* laptop-automute - 2ch only */
759 static void ad1986a_update_hp(struct hda_codec *codec)
761 struct ad198x_spec *spec = codec->spec;
764 if (spec->jack_present)
765 mute = HDA_AMP_MUTE; /* mute internal speaker */
767 /* unmute internal speaker if necessary */
768 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
769 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
773 static void ad1986a_hp_automute(struct hda_codec *codec)
775 struct ad198x_spec *spec = codec->spec;
776 unsigned int present;
778 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
779 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
780 spec->jack_present = !(present & 0x80000000);
781 ad1986a_update_hp(codec);
784 #define AD1986A_HP_EVENT 0x37
786 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
788 if ((res >> 26) != AD1986A_HP_EVENT)
790 ad1986a_hp_automute(codec);
793 static int ad1986a_hp_init(struct hda_codec *codec)
796 ad1986a_hp_automute(codec);
800 /* bind hp and internal speaker mute (with plug check) */
801 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
802 struct snd_ctl_elem_value *ucontrol)
804 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
805 long *valp = ucontrol->value.integer.value;
808 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
810 valp[0] ? 0 : HDA_AMP_MUTE);
811 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
813 valp[1] ? 0 : HDA_AMP_MUTE);
815 ad1986a_update_hp(codec);
819 static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
820 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
822 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
823 .name = "Master Playback Switch",
824 .info = snd_hda_mixer_amp_switch_info,
825 .get = snd_hda_mixer_amp_switch_get,
826 .put = ad1986a_hp_master_sw_put,
827 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
829 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
830 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
831 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
832 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
833 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
834 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
835 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
836 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
837 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
839 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
840 .name = "Capture Source",
841 .info = ad198x_mux_enum_info,
842 .get = ad198x_mux_enum_get,
843 .put = ad198x_mux_enum_put,
846 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
847 .name = "External Amplifier",
848 .info = ad198x_eapd_info,
849 .get = ad198x_eapd_get,
850 .put = ad198x_eapd_put,
851 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
857 * initialization verbs
859 static struct hda_verb ad1986a_init_verbs[] = {
860 /* Front, Surround, CLFE DAC; mute as default */
861 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
862 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
863 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
865 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
866 /* HP, Line-Out, Surround, CLFE selectors */
867 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
868 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
869 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
870 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
872 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
873 /* Mic selector: Mic 1/2 pin */
874 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
875 /* Line-in selector: Line-in */
876 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
878 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
879 /* Record selector: mic */
880 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
881 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
882 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
883 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
884 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
885 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
886 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
888 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
889 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
890 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
891 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
892 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
893 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
894 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
896 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
897 /* Front, Surround, CLFE Pins */
898 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
899 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
900 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
902 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
904 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
905 /* Line, Aux, CD, Beep-In Pin */
906 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
907 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
908 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
909 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
910 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
914 static struct hda_verb ad1986a_ch2_init[] = {
915 /* Surround out -> Line In */
916 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
917 /* Line-in selectors */
918 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
920 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
921 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
922 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
926 static struct hda_verb ad1986a_ch4_init[] = {
927 /* Surround out -> Surround */
928 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
929 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
931 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
932 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
936 static struct hda_verb ad1986a_ch6_init[] = {
937 /* Surround out -> Surround out */
938 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
939 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
941 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
942 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
946 static struct hda_channel_mode ad1986a_modes[3] = {
947 { 2, ad1986a_ch2_init },
948 { 4, ad1986a_ch4_init },
949 { 6, ad1986a_ch6_init },
952 /* eapd initialization */
953 static struct hda_verb ad1986a_eapd_init_verbs[] = {
954 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
958 static struct hda_verb ad1986a_automic_verbs[] = {
959 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
960 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
961 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
962 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
963 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
967 /* Ultra initialization */
968 static struct hda_verb ad1986a_ultra_init[] = {
969 /* eapd initialization */
970 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
972 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
973 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
974 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
978 /* pin sensing on HP jack */
979 static struct hda_verb ad1986a_hp_init_verbs[] = {
980 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
991 AD1986A_LAPTOP_AUTOMUTE,
997 static const char *ad1986a_models[AD1986A_MODELS] = {
998 [AD1986A_6STACK] = "6stack",
999 [AD1986A_3STACK] = "3stack",
1000 [AD1986A_LAPTOP] = "laptop",
1001 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1002 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1003 [AD1986A_ULTRA] = "ultra",
1004 [AD1986A_SAMSUNG] = "samsung",
1007 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1008 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1009 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1010 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1011 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1012 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1013 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1014 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1015 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1016 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1017 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1018 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1019 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1020 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1021 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1022 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1023 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1024 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
1025 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1026 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1027 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1028 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1029 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1030 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1031 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1032 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1033 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1037 #ifdef CONFIG_SND_HDA_POWER_SAVE
1038 static struct hda_amp_list ad1986a_loopbacks[] = {
1039 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1040 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1041 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1042 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1043 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1048 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1050 unsigned int conf = snd_hda_codec_read(codec, nid, 0,
1051 AC_VERB_GET_CONFIG_DEFAULT, 0);
1052 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1055 static int patch_ad1986a(struct hda_codec *codec)
1057 struct ad198x_spec *spec;
1058 int err, board_config;
1060 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1066 err = snd_hda_attach_beep_device(codec, 0x19);
1071 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1073 spec->multiout.max_channels = 6;
1074 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1075 spec->multiout.dac_nids = ad1986a_dac_nids;
1076 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1077 spec->num_adc_nids = 1;
1078 spec->adc_nids = ad1986a_adc_nids;
1079 spec->capsrc_nids = ad1986a_capsrc_nids;
1080 spec->input_mux = &ad1986a_capture_source;
1081 spec->num_mixers = 1;
1082 spec->mixers[0] = ad1986a_mixers;
1083 spec->num_init_verbs = 1;
1084 spec->init_verbs[0] = ad1986a_init_verbs;
1085 #ifdef CONFIG_SND_HDA_POWER_SAVE
1086 spec->loopback.amplist = ad1986a_loopbacks;
1088 spec->vmaster_nid = 0x1b;
1090 codec->patch_ops = ad198x_patch_ops;
1092 /* override some parameters */
1093 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1096 switch (board_config) {
1097 case AD1986A_3STACK:
1098 spec->num_mixers = 2;
1099 spec->mixers[1] = ad1986a_3st_mixers;
1100 spec->num_init_verbs = 2;
1101 spec->init_verbs[1] = ad1986a_ch2_init;
1102 spec->channel_mode = ad1986a_modes;
1103 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1104 spec->need_dac_fix = 1;
1105 spec->multiout.max_channels = 2;
1106 spec->multiout.num_dacs = 1;
1108 case AD1986A_LAPTOP:
1109 spec->mixers[0] = ad1986a_laptop_mixers;
1110 spec->multiout.max_channels = 2;
1111 spec->multiout.num_dacs = 1;
1112 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1114 case AD1986A_LAPTOP_EAPD:
1115 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1116 spec->num_init_verbs = 2;
1117 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1118 spec->multiout.max_channels = 2;
1119 spec->multiout.num_dacs = 1;
1120 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1121 if (!is_jack_available(codec, 0x25))
1122 spec->multiout.dig_out_nid = 0;
1123 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1125 case AD1986A_SAMSUNG:
1126 spec->mixers[0] = ad1986a_samsung_mixers;
1127 spec->num_init_verbs = 3;
1128 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1129 spec->init_verbs[2] = ad1986a_automic_verbs;
1130 spec->multiout.max_channels = 2;
1131 spec->multiout.num_dacs = 1;
1132 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1133 if (!is_jack_available(codec, 0x25))
1134 spec->multiout.dig_out_nid = 0;
1135 spec->input_mux = &ad1986a_automic_capture_source;
1136 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1137 codec->patch_ops.init = ad1986a_automic_init;
1139 case AD1986A_LAPTOP_AUTOMUTE:
1140 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1141 spec->num_init_verbs = 3;
1142 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1143 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1144 spec->multiout.max_channels = 2;
1145 spec->multiout.num_dacs = 1;
1146 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1147 if (!is_jack_available(codec, 0x25))
1148 spec->multiout.dig_out_nid = 0;
1149 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1150 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1151 codec->patch_ops.init = ad1986a_hp_init;
1154 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1155 spec->num_init_verbs = 2;
1156 spec->init_verbs[1] = ad1986a_ultra_init;
1157 spec->multiout.max_channels = 2;
1158 spec->multiout.num_dacs = 1;
1159 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1160 spec->multiout.dig_out_nid = 0;
1164 /* AD1986A has a hardware problem that it can't share a stream
1165 * with multiple output pins. The copy of front to surrounds
1166 * causes noisy or silent outputs at a certain timing, e.g.
1167 * changing the volume.
1168 * So, let's disable the shared stream.
1170 spec->multiout.no_share_stream = 1;
1179 #define AD1983_SPDIF_OUT 0x02
1180 #define AD1983_DAC 0x03
1181 #define AD1983_ADC 0x04
1183 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1184 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1185 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1187 static struct hda_input_mux ad1983_capture_source = {
1193 { "Mix Mono", 0x3 },
1198 * SPDIF playback route
1200 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1202 static char *texts[] = { "PCM", "ADC" };
1204 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1206 uinfo->value.enumerated.items = 2;
1207 if (uinfo->value.enumerated.item > 1)
1208 uinfo->value.enumerated.item = 1;
1209 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1213 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1215 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1216 struct ad198x_spec *spec = codec->spec;
1218 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1222 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1224 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1225 struct ad198x_spec *spec = codec->spec;
1227 if (ucontrol->value.enumerated.item[0] > 1)
1229 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1230 spec->spdif_route = ucontrol->value.enumerated.item[0];
1231 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1232 AC_VERB_SET_CONNECT_SEL,
1239 static struct snd_kcontrol_new ad1983_mixers[] = {
1240 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1241 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1242 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1243 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1244 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1245 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1246 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1247 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1248 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1249 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1250 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1251 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1252 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1253 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1254 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1256 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1257 .name = "Capture Source",
1258 .info = ad198x_mux_enum_info,
1259 .get = ad198x_mux_enum_get,
1260 .put = ad198x_mux_enum_put,
1263 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1264 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1265 .info = ad1983_spdif_route_info,
1266 .get = ad1983_spdif_route_get,
1267 .put = ad1983_spdif_route_put,
1272 static struct hda_verb ad1983_init_verbs[] = {
1273 /* Front, HP, Mono; mute as default */
1274 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1275 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1276 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1277 /* Beep, PCM, Mic, Line-In: mute */
1278 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1279 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1280 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1281 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1282 /* Front, HP selectors; from Mix */
1283 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1284 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1285 /* Mono selector; from Mix */
1286 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1287 /* Mic selector; Mic */
1288 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1289 /* Line-in selector: Line-in */
1290 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1291 /* Mic boost: 0dB */
1292 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1293 /* Record selector: mic */
1294 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1295 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1296 /* SPDIF route: PCM */
1297 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1299 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1301 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1303 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1305 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1307 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1311 #ifdef CONFIG_SND_HDA_POWER_SAVE
1312 static struct hda_amp_list ad1983_loopbacks[] = {
1313 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1314 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1319 static int patch_ad1983(struct hda_codec *codec)
1321 struct ad198x_spec *spec;
1324 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1330 err = snd_hda_attach_beep_device(codec, 0x10);
1335 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1337 spec->multiout.max_channels = 2;
1338 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1339 spec->multiout.dac_nids = ad1983_dac_nids;
1340 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1341 spec->num_adc_nids = 1;
1342 spec->adc_nids = ad1983_adc_nids;
1343 spec->capsrc_nids = ad1983_capsrc_nids;
1344 spec->input_mux = &ad1983_capture_source;
1345 spec->num_mixers = 1;
1346 spec->mixers[0] = ad1983_mixers;
1347 spec->num_init_verbs = 1;
1348 spec->init_verbs[0] = ad1983_init_verbs;
1349 spec->spdif_route = 0;
1350 #ifdef CONFIG_SND_HDA_POWER_SAVE
1351 spec->loopback.amplist = ad1983_loopbacks;
1353 spec->vmaster_nid = 0x05;
1355 codec->patch_ops = ad198x_patch_ops;
1362 * AD1981 HD specific
1365 #define AD1981_SPDIF_OUT 0x02
1366 #define AD1981_DAC 0x03
1367 #define AD1981_ADC 0x04
1369 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1370 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1371 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1373 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1374 static struct hda_input_mux ad1981_capture_source = {
1377 { "Front Mic", 0x0 },
1380 { "Mix Mono", 0x3 },
1387 static struct snd_kcontrol_new ad1981_mixers[] = {
1388 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1389 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1390 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1391 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1392 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1393 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1394 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1395 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1396 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1397 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1398 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1399 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1400 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1401 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1402 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1403 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1404 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1405 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1406 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1407 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1408 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1409 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412 .name = "Capture Source",
1413 .info = ad198x_mux_enum_info,
1414 .get = ad198x_mux_enum_get,
1415 .put = ad198x_mux_enum_put,
1417 /* identical with AD1983 */
1419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1421 .info = ad1983_spdif_route_info,
1422 .get = ad1983_spdif_route_get,
1423 .put = ad1983_spdif_route_put,
1428 static struct hda_verb ad1981_init_verbs[] = {
1429 /* Front, HP, Mono; mute as default */
1430 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1431 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1432 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1433 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1434 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1435 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1436 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1437 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1438 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1439 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1440 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1441 /* Front, HP selectors; from Mix */
1442 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1443 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1444 /* Mono selector; from Mix */
1445 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1446 /* Mic Mixer; select Front Mic */
1447 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1448 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1449 /* Mic boost: 0dB */
1450 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1451 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1452 /* Record selector: Front mic */
1453 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1454 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1455 /* SPDIF route: PCM */
1456 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1458 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1460 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1462 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1463 /* Front & Rear Mic Pins */
1464 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1465 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1467 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1469 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1470 /* Line-Out as Input: disabled */
1471 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1475 #ifdef CONFIG_SND_HDA_POWER_SAVE
1476 static struct hda_amp_list ad1981_loopbacks[] = {
1477 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1478 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1479 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1480 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1481 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1487 * Patch for HP nx6320
1489 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1490 * speaker output enabled _and_ mute-LED off.
1493 #define AD1981_HP_EVENT 0x37
1494 #define AD1981_MIC_EVENT 0x38
1496 static struct hda_verb ad1981_hp_init_verbs[] = {
1497 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1498 /* pin sensing on HP and Mic jacks */
1499 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1500 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1504 /* turn on/off EAPD (+ mute HP) as a master switch */
1505 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1506 struct snd_ctl_elem_value *ucontrol)
1508 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1509 struct ad198x_spec *spec = codec->spec;
1511 if (! ad198x_eapd_put(kcontrol, ucontrol))
1513 /* change speaker pin appropriately */
1514 snd_hda_codec_write(codec, 0x05, 0,
1515 AC_VERB_SET_PIN_WIDGET_CONTROL,
1516 spec->cur_eapd ? PIN_OUT : 0);
1517 /* toggle HP mute appropriately */
1518 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1520 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1524 /* bind volumes of both NID 0x05 and 0x06 */
1525 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1526 .ops = &snd_hda_bind_vol,
1528 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1529 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1534 /* mute internal speaker if HP is plugged */
1535 static void ad1981_hp_automute(struct hda_codec *codec)
1537 unsigned int present;
1539 present = snd_hda_codec_read(codec, 0x06, 0,
1540 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1541 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1542 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1545 /* toggle input of built-in and mic jack appropriately */
1546 static void ad1981_hp_automic(struct hda_codec *codec)
1548 static struct hda_verb mic_jack_on[] = {
1549 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1550 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1553 static struct hda_verb mic_jack_off[] = {
1554 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1555 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1558 unsigned int present;
1560 present = snd_hda_codec_read(codec, 0x08, 0,
1561 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1563 snd_hda_sequence_write(codec, mic_jack_on);
1565 snd_hda_sequence_write(codec, mic_jack_off);
1568 /* unsolicited event for HP jack sensing */
1569 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1574 case AD1981_HP_EVENT:
1575 ad1981_hp_automute(codec);
1577 case AD1981_MIC_EVENT:
1578 ad1981_hp_automic(codec);
1583 static struct hda_input_mux ad1981_hp_capture_source = {
1587 { "Docking-Station", 0x1 },
1592 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1593 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1595 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1596 .name = "Master Playback Switch",
1597 .info = ad198x_eapd_info,
1598 .get = ad198x_eapd_get,
1599 .put = ad1981_hp_master_sw_put,
1600 .private_value = 0x05,
1602 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1603 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1605 /* FIXME: analog mic/line loopback doesn't work with my tests...
1606 * (although recording is OK)
1608 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1609 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1610 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1611 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1612 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1613 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1614 /* FIXME: does this laptop have analog CD connection? */
1615 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1616 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1618 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1619 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1620 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1621 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1623 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1624 .name = "Capture Source",
1625 .info = ad198x_mux_enum_info,
1626 .get = ad198x_mux_enum_get,
1627 .put = ad198x_mux_enum_put,
1632 /* initialize jack-sensing, too */
1633 static int ad1981_hp_init(struct hda_codec *codec)
1636 ad1981_hp_automute(codec);
1637 ad1981_hp_automic(codec);
1641 /* configuration for Toshiba Laptops */
1642 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1643 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1644 /* pin sensing on HP and Mic jacks */
1645 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1646 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1650 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1651 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1652 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1656 /* configuration for Lenovo Thinkpad T60 */
1657 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1658 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1659 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1660 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1661 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1662 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1663 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1664 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1665 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1666 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1667 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1668 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671 .name = "Capture Source",
1672 .info = ad198x_mux_enum_info,
1673 .get = ad198x_mux_enum_get,
1674 .put = ad198x_mux_enum_put,
1676 /* identical with AD1983 */
1678 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1679 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1680 .info = ad1983_spdif_route_info,
1681 .get = ad1983_spdif_route_get,
1682 .put = ad1983_spdif_route_put,
1687 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1705 static const char *ad1981_models[AD1981_MODELS] = {
1707 [AD1981_THINKPAD] = "thinkpad",
1708 [AD1981_BASIC] = "basic",
1709 [AD1981_TOSHIBA] = "toshiba"
1712 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1713 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1714 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1716 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1717 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1718 /* Lenovo Thinkpad T60/X60/Z6xx */
1719 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1720 /* HP nx6320 (reversed SSID, H/W bug) */
1721 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1725 static int patch_ad1981(struct hda_codec *codec)
1727 struct ad198x_spec *spec;
1728 int err, board_config;
1730 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1736 err = snd_hda_attach_beep_device(codec, 0x10);
1741 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1743 spec->multiout.max_channels = 2;
1744 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1745 spec->multiout.dac_nids = ad1981_dac_nids;
1746 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1747 spec->num_adc_nids = 1;
1748 spec->adc_nids = ad1981_adc_nids;
1749 spec->capsrc_nids = ad1981_capsrc_nids;
1750 spec->input_mux = &ad1981_capture_source;
1751 spec->num_mixers = 1;
1752 spec->mixers[0] = ad1981_mixers;
1753 spec->num_init_verbs = 1;
1754 spec->init_verbs[0] = ad1981_init_verbs;
1755 spec->spdif_route = 0;
1756 #ifdef CONFIG_SND_HDA_POWER_SAVE
1757 spec->loopback.amplist = ad1981_loopbacks;
1759 spec->vmaster_nid = 0x05;
1761 codec->patch_ops = ad198x_patch_ops;
1763 /* override some parameters */
1764 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1767 switch (board_config) {
1769 spec->mixers[0] = ad1981_hp_mixers;
1770 spec->num_init_verbs = 2;
1771 spec->init_verbs[1] = ad1981_hp_init_verbs;
1772 spec->multiout.dig_out_nid = 0;
1773 spec->input_mux = &ad1981_hp_capture_source;
1775 codec->patch_ops.init = ad1981_hp_init;
1776 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1778 case AD1981_THINKPAD:
1779 spec->mixers[0] = ad1981_thinkpad_mixers;
1780 spec->input_mux = &ad1981_thinkpad_capture_source;
1782 case AD1981_TOSHIBA:
1783 spec->mixers[0] = ad1981_hp_mixers;
1784 spec->mixers[1] = ad1981_toshiba_mixers;
1785 spec->num_init_verbs = 2;
1786 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1787 spec->multiout.dig_out_nid = 0;
1788 spec->input_mux = &ad1981_hp_capture_source;
1789 codec->patch_ops.init = ad1981_hp_init;
1790 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1800 * Output pins and routes
1802 * Pin Mix Sel DAC (*)
1803 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1804 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1805 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1806 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1807 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1808 * port-F 0x16 (mute) <- 0x2a <- 06
1809 * port-G 0x24 (mute) <- 0x27 <- 05
1810 * port-H 0x25 (mute) <- 0x28 <- 0a
1811 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1813 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1814 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1816 * Input pins and routes
1818 * pin boost mix input # / adc input #
1819 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1820 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1821 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1822 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1823 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1824 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1825 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1826 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1830 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1831 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1833 * Inputs of Analog Mix (0x20)
1834 * 0:Port-B (front mic)
1835 * 1:Port-C/G/H (line-in)
1837 * 3:Port-D (line-in/2)
1838 * 4:Port-E/G/H (mic-in)
1839 * 5:Port-F (mic2-in)
1845 * 1:Port-B (front mic-in)
1846 * 2:Port-C (line-in)
1847 * 3:Port-F (mic2-in)
1852 * 8:Port-D (line-in/2)
1855 * Proposed pin assignments by the datasheet
1858 * Port-A front headphone
1868 * Port-A front headphone
1870 * C rear line-in/surround
1872 * E rear mic-in/CLFE
1878 * D internal speaker (with EAPD)
1879 * E/F quad mic array
1895 /* reivision id to check workarounds */
1896 #define AD1988A_REV2 0x100200
1898 #define is_rev2(codec) \
1899 ((codec)->vendor_id == 0x11d41988 && \
1900 (codec)->revision_id == AD1988A_REV2)
1906 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1907 0x04, 0x06, 0x05, 0x0a
1910 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1914 /* for AD1988A revision-2, DAC2-4 are swapped */
1915 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1916 0x04, 0x05, 0x0a, 0x06
1919 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1923 static hda_nid_t ad1988_adc_nids[3] = {
1927 static hda_nid_t ad1988_capsrc_nids[3] = {
1931 #define AD1988_SPDIF_OUT 0x02
1932 #define AD1988_SPDIF_OUT_HDMI 0x0b
1933 #define AD1988_SPDIF_IN 0x07
1935 static hda_nid_t ad1989b_slave_dig_outs[] = {
1936 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
1939 static struct hda_input_mux ad1988_6stack_capture_source = {
1942 { "Front Mic", 0x1 }, /* port-B */
1943 { "Line", 0x2 }, /* port-C */
1944 { "Mic", 0x4 }, /* port-E */
1950 static struct hda_input_mux ad1988_laptop_capture_source = {
1953 { "Mic/Line", 0x1 }, /* port-B */
1961 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1962 struct snd_ctl_elem_info *uinfo)
1964 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1965 struct ad198x_spec *spec = codec->spec;
1966 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1967 spec->num_channel_mode);
1970 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1971 struct snd_ctl_elem_value *ucontrol)
1973 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1974 struct ad198x_spec *spec = codec->spec;
1975 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1976 spec->num_channel_mode, spec->multiout.max_channels);
1979 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1980 struct snd_ctl_elem_value *ucontrol)
1982 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1983 struct ad198x_spec *spec = codec->spec;
1984 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1985 spec->num_channel_mode,
1986 &spec->multiout.max_channels);
1987 if (err >= 0 && spec->need_dac_fix)
1988 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1993 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1994 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1995 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1996 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1997 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1998 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2002 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2003 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2004 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2005 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2006 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2007 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2011 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2012 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2013 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2014 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2015 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2016 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2017 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2018 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2020 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2021 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2022 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2023 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2024 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2025 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2026 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2027 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2029 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2030 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2032 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2033 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2039 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2040 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2041 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2042 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2043 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2047 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2048 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2049 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2050 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2051 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2055 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2056 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2057 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2058 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2059 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2060 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2061 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2063 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2064 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2065 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2066 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2067 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2068 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2069 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2070 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2072 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2073 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2075 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2076 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2078 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2079 .name = "Channel Mode",
2080 .info = ad198x_ch_mode_info,
2081 .get = ad198x_ch_mode_get,
2082 .put = ad198x_ch_mode_put,
2089 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2090 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2091 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2092 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2094 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2095 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2096 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2097 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2098 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2099 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2101 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2102 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2104 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2107 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2108 .name = "External Amplifier",
2109 .info = ad198x_eapd_info,
2110 .get = ad198x_eapd_get,
2111 .put = ad198x_eapd_put,
2112 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2119 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2120 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2121 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2122 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2123 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2124 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2125 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2127 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2128 /* The multiple "Capture Source" controls confuse alsamixer
2129 * So call somewhat different..
2131 /* .name = "Capture Source", */
2132 .name = "Input Source",
2134 .info = ad198x_mux_enum_info,
2135 .get = ad198x_mux_enum_get,
2136 .put = ad198x_mux_enum_put,
2141 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2142 struct snd_ctl_elem_info *uinfo)
2144 static char *texts[] = {
2145 "PCM", "ADC1", "ADC2", "ADC3"
2147 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2149 uinfo->value.enumerated.items = 4;
2150 if (uinfo->value.enumerated.item >= 4)
2151 uinfo->value.enumerated.item = 3;
2152 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2156 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2157 struct snd_ctl_elem_value *ucontrol)
2159 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2162 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2165 ucontrol->value.enumerated.item[0] = 0;
2167 sel = snd_hda_codec_read(codec, 0x0b, 0,
2168 AC_VERB_GET_CONNECT_SEL, 0);
2173 ucontrol->value.enumerated.item[0] = sel;
2178 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2179 struct snd_ctl_elem_value *ucontrol)
2181 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2182 unsigned int val, sel;
2185 val = ucontrol->value.enumerated.item[0];
2189 sel = snd_hda_codec_read(codec, 0x1d, 0,
2190 AC_VERB_GET_AMP_GAIN_MUTE,
2192 change = sel & 0x80;
2194 snd_hda_codec_write_cache(codec, 0x1d, 0,
2195 AC_VERB_SET_AMP_GAIN_MUTE,
2197 snd_hda_codec_write_cache(codec, 0x1d, 0,
2198 AC_VERB_SET_AMP_GAIN_MUTE,
2202 sel = snd_hda_codec_read(codec, 0x1d, 0,
2203 AC_VERB_GET_AMP_GAIN_MUTE,
2204 AC_AMP_GET_INPUT | 0x01);
2205 change = sel & 0x80;
2207 snd_hda_codec_write_cache(codec, 0x1d, 0,
2208 AC_VERB_SET_AMP_GAIN_MUTE,
2210 snd_hda_codec_write_cache(codec, 0x1d, 0,
2211 AC_VERB_SET_AMP_GAIN_MUTE,
2214 sel = snd_hda_codec_read(codec, 0x0b, 0,
2215 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2216 change |= sel != val;
2218 snd_hda_codec_write_cache(codec, 0x0b, 0,
2219 AC_VERB_SET_CONNECT_SEL,
2225 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2226 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2228 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2229 .name = "IEC958 Playback Source",
2230 .info = ad1988_spdif_playback_source_info,
2231 .get = ad1988_spdif_playback_source_get,
2232 .put = ad1988_spdif_playback_source_put,
2237 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2238 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2242 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2243 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2244 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2249 * initialization verbs
2253 * for 6-stack (+dig)
2255 static struct hda_verb ad1988_6stack_init_verbs[] = {
2256 /* Front, Surround, CLFE, side DAC; unmute as default */
2257 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2258 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2259 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2260 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2261 /* Port-A front headphon path */
2262 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2263 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2264 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2265 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2266 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2267 /* Port-D line-out path */
2268 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2269 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2270 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2271 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2272 /* Port-F surround path */
2273 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2274 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2275 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2276 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2277 /* Port-G CLFE path */
2278 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2279 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2280 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2281 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2282 /* Port-H side path */
2283 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2284 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2285 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2286 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2288 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2289 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2290 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2291 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2292 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2293 /* Port-B front mic-in path */
2294 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2295 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2296 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2297 /* Port-C line-in path */
2298 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2299 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2300 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2301 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2302 /* Port-E mic-in path */
2303 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2304 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2305 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2306 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2307 /* Analog CD Input */
2308 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2309 /* Analog Mix output amp */
2310 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2315 static struct hda_verb ad1988_capture_init_verbs[] = {
2316 /* mute analog mix */
2317 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2318 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2319 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2320 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2321 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2322 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2323 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2324 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2325 /* select ADCs - front-mic */
2326 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2327 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2328 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2333 static struct hda_verb ad1988_spdif_init_verbs[] = {
2335 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2336 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2337 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2338 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2340 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2345 /* AD1989 has no ADC -> SPDIF route */
2346 static struct hda_verb ad1989_spdif_init_verbs[] = {
2347 /* SPDIF-1 out pin */
2348 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2349 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2350 /* SPDIF-2/HDMI out pin */
2351 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2352 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2357 * verbs for 3stack (+dig)
2359 static struct hda_verb ad1988_3stack_ch2_init[] = {
2360 /* set port-C to line-in */
2361 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2362 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2363 /* set port-E to mic-in */
2364 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2365 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2369 static struct hda_verb ad1988_3stack_ch6_init[] = {
2370 /* set port-C to surround out */
2371 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2372 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2373 /* set port-E to CLFE out */
2374 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2375 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2379 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2380 { 2, ad1988_3stack_ch2_init },
2381 { 6, ad1988_3stack_ch6_init },
2384 static struct hda_verb ad1988_3stack_init_verbs[] = {
2385 /* Front, Surround, CLFE, side DAC; unmute as default */
2386 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2387 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2388 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2389 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2390 /* Port-A front headphon path */
2391 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2392 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2393 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2394 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2395 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2396 /* Port-D line-out path */
2397 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2398 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2399 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2400 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2402 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2403 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2404 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2405 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2406 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2407 /* Port-B front mic-in path */
2408 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2409 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2410 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2411 /* Port-C line-in/surround path - 6ch mode as default */
2412 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2413 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2414 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2415 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2416 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2417 /* Port-E mic-in/CLFE path - 6ch mode as default */
2418 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2419 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2420 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2421 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2422 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2423 /* mute analog mix */
2424 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2425 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2426 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2427 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2428 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2429 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2430 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2431 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2432 /* select ADCs - front-mic */
2433 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2434 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2435 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2436 /* Analog Mix output amp */
2437 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2442 * verbs for laptop mode (+dig)
2444 static struct hda_verb ad1988_laptop_hp_on[] = {
2445 /* unmute port-A and mute port-D */
2446 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2447 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2450 static struct hda_verb ad1988_laptop_hp_off[] = {
2451 /* mute port-A and unmute port-D */
2452 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2453 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2457 #define AD1988_HP_EVENT 0x01
2459 static struct hda_verb ad1988_laptop_init_verbs[] = {
2460 /* Front, Surround, CLFE, side DAC; unmute as default */
2461 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2462 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2463 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2464 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2465 /* Port-A front headphon path */
2466 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2467 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2468 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2469 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2470 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2471 /* unsolicited event for pin-sense */
2472 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2473 /* Port-D line-out path + EAPD */
2474 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2475 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2476 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2477 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2478 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2480 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2481 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2482 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2483 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2484 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2485 /* Port-B mic-in path */
2486 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2487 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2488 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2489 /* Port-C docking station - try to output */
2490 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2491 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2492 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2493 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2494 /* mute analog mix */
2495 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2496 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2497 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2498 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2499 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2500 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2501 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2502 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2503 /* select ADCs - mic */
2504 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2505 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2506 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2507 /* Analog Mix output amp */
2508 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2512 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2514 if ((res >> 26) != AD1988_HP_EVENT)
2516 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2517 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2519 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2522 #ifdef CONFIG_SND_HDA_POWER_SAVE
2523 static struct hda_amp_list ad1988_loopbacks[] = {
2524 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2525 { 0x20, HDA_INPUT, 1 }, /* Line */
2526 { 0x20, HDA_INPUT, 4 }, /* Mic */
2527 { 0x20, HDA_INPUT, 6 }, /* CD */
2533 * Automatic parse of I/O pins from the BIOS configuration
2541 static struct snd_kcontrol_new ad1988_control_templates[] = {
2542 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2543 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2544 HDA_BIND_MUTE(NULL, 0, 0, 0),
2547 /* add dynamic controls */
2548 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2551 struct snd_kcontrol_new *knew;
2553 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2554 knew = snd_array_new(&spec->kctls);
2557 *knew = ad1988_control_templates[type];
2558 knew->name = kstrdup(name, GFP_KERNEL);
2561 knew->private_value = val;
2565 #define AD1988_PIN_CD_NID 0x18
2566 #define AD1988_PIN_BEEP_NID 0x10
2568 static hda_nid_t ad1988_mixer_nids[8] = {
2569 /* A B C D E F G H */
2570 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2573 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2575 static hda_nid_t idx_to_dac[8] = {
2576 /* A B C D E F G H */
2577 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2579 static hda_nid_t idx_to_dac_rev2[8] = {
2580 /* A B C D E F G H */
2581 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2584 return idx_to_dac_rev2[idx];
2586 return idx_to_dac[idx];
2589 static hda_nid_t ad1988_boost_nids[8] = {
2590 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2593 static int ad1988_pin_idx(hda_nid_t nid)
2595 static hda_nid_t ad1988_io_pins[8] = {
2596 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2599 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2600 if (ad1988_io_pins[i] == nid)
2602 return 0; /* should be -1 */
2605 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2607 static int loopback_idx[8] = {
2608 2, 0, 1, 3, 4, 5, 1, 4
2611 case AD1988_PIN_CD_NID:
2614 return loopback_idx[ad1988_pin_idx(nid)];
2618 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2620 static int adc_idx[8] = {
2621 0, 1, 2, 8, 4, 3, 6, 7
2624 case AD1988_PIN_CD_NID:
2627 return adc_idx[ad1988_pin_idx(nid)];
2631 /* fill in the dac_nids table from the parsed pin configuration */
2632 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2633 const struct auto_pin_cfg *cfg)
2635 struct ad198x_spec *spec = codec->spec;
2638 spec->multiout.dac_nids = spec->private_dac_nids;
2640 /* check the pins hardwired to audio widget */
2641 for (i = 0; i < cfg->line_outs; i++) {
2642 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2643 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2645 spec->multiout.num_dacs = cfg->line_outs;
2649 /* add playback controls from the parsed DAC table */
2650 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2651 const struct auto_pin_cfg *cfg)
2654 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2658 for (i = 0; i < cfg->line_outs; i++) {
2659 hda_nid_t dac = spec->multiout.dac_nids[i];
2662 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2665 err = add_control(spec, AD_CTL_WIDGET_VOL,
2666 "Center Playback Volume",
2667 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2670 err = add_control(spec, AD_CTL_WIDGET_VOL,
2671 "LFE Playback Volume",
2672 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2675 err = add_control(spec, AD_CTL_BIND_MUTE,
2676 "Center Playback Switch",
2677 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2680 err = add_control(spec, AD_CTL_BIND_MUTE,
2681 "LFE Playback Switch",
2682 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2686 sprintf(name, "%s Playback Volume", chname[i]);
2687 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2688 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2691 sprintf(name, "%s Playback Switch", chname[i]);
2692 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2693 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2701 /* add playback controls for speaker and HP outputs */
2702 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2705 struct ad198x_spec *spec = codec->spec;
2713 idx = ad1988_pin_idx(pin);
2714 nid = ad1988_idx_to_dac(codec, idx);
2715 /* check whether the corresponding DAC was already taken */
2716 for (i = 0; i < spec->autocfg.line_outs; i++) {
2717 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2718 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2722 if (i >= spec->autocfg.line_outs) {
2723 /* specify the DAC as the extra output */
2724 if (!spec->multiout.hp_nid)
2725 spec->multiout.hp_nid = nid;
2727 spec->multiout.extra_out_nid[0] = nid;
2728 /* control HP volume/switch on the output mixer amp */
2729 sprintf(name, "%s Playback Volume", pfx);
2730 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2731 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2735 nid = ad1988_mixer_nids[idx];
2736 sprintf(name, "%s Playback Switch", pfx);
2737 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2738 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2743 /* create input playback/capture controls for the given pin */
2744 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2745 const char *ctlname, int boost)
2750 sprintf(name, "%s Playback Volume", ctlname);
2751 idx = ad1988_pin_to_loopback_idx(pin);
2752 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2753 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2755 sprintf(name, "%s Playback Switch", ctlname);
2756 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2757 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2761 idx = ad1988_pin_idx(pin);
2762 bnid = ad1988_boost_nids[idx];
2764 sprintf(name, "%s Boost", ctlname);
2765 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2766 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2773 /* create playback/capture controls for input pins */
2774 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2775 const struct auto_pin_cfg *cfg)
2777 struct hda_input_mux *imux = &spec->private_imux;
2780 for (i = 0; i < AUTO_PIN_LAST; i++) {
2781 err = new_analog_input(spec, cfg->input_pins[i],
2782 auto_pin_cfg_labels[i],
2783 i <= AUTO_PIN_FRONT_MIC);
2786 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2787 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2790 imux->items[imux->num_items].label = "Mix";
2791 imux->items[imux->num_items].index = 9;
2794 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2795 "Analog Mix Playback Volume",
2796 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2798 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2799 "Analog Mix Playback Switch",
2800 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2806 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2807 hda_nid_t nid, int pin_type,
2811 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2812 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2814 case 0x11: /* port-A - DAC 04 */
2815 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2817 case 0x14: /* port-B - DAC 06 */
2818 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2820 case 0x15: /* port-C - DAC 05 */
2821 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2823 case 0x17: /* port-E - DAC 0a */
2824 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2826 case 0x13: /* mono - DAC 04 */
2827 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2832 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2834 struct ad198x_spec *spec = codec->spec;
2837 for (i = 0; i < spec->autocfg.line_outs; i++) {
2838 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2839 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2843 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2845 struct ad198x_spec *spec = codec->spec;
2848 pin = spec->autocfg.speaker_pins[0];
2849 if (pin) /* connect to front */
2850 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2851 pin = spec->autocfg.hp_pins[0];
2852 if (pin) /* connect to front */
2853 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2856 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2858 struct ad198x_spec *spec = codec->spec;
2861 for (i = 0; i < AUTO_PIN_LAST; i++) {
2862 hda_nid_t nid = spec->autocfg.input_pins[i];
2866 case 0x15: /* port-C */
2867 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2869 case 0x17: /* port-E */
2870 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2873 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2874 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2875 if (nid != AD1988_PIN_CD_NID)
2876 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2878 idx = ad1988_pin_idx(nid);
2879 if (ad1988_boost_nids[idx])
2880 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2881 AC_VERB_SET_AMP_GAIN_MUTE,
2886 /* parse the BIOS configuration and set up the alc_spec */
2887 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2888 static int ad1988_parse_auto_config(struct hda_codec *codec)
2890 struct ad198x_spec *spec = codec->spec;
2893 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2895 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2897 if (! spec->autocfg.line_outs)
2898 return 0; /* can't find valid BIOS pin config */
2899 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2900 (err = ad1988_auto_create_extra_out(codec,
2901 spec->autocfg.speaker_pins[0],
2903 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2904 "Headphone")) < 0 ||
2905 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2908 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2910 if (spec->autocfg.dig_outs)
2911 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2912 if (spec->autocfg.dig_in_pin)
2913 spec->dig_in_nid = AD1988_SPDIF_IN;
2915 if (spec->kctls.list)
2916 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2918 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2920 spec->input_mux = &spec->private_imux;
2925 /* init callback for auto-configuration model -- overriding the default init */
2926 static int ad1988_auto_init(struct hda_codec *codec)
2929 ad1988_auto_init_multi_out(codec);
2930 ad1988_auto_init_extra_out(codec);
2931 ad1988_auto_init_analog_input(codec);
2939 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2940 [AD1988_6STACK] = "6stack",
2941 [AD1988_6STACK_DIG] = "6stack-dig",
2942 [AD1988_3STACK] = "3stack",
2943 [AD1988_3STACK_DIG] = "3stack-dig",
2944 [AD1988_LAPTOP] = "laptop",
2945 [AD1988_LAPTOP_DIG] = "laptop-dig",
2946 [AD1988_AUTO] = "auto",
2949 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2950 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2951 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2952 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
2953 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
2957 static int patch_ad1988(struct hda_codec *codec)
2959 struct ad198x_spec *spec;
2960 int err, board_config;
2962 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2969 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2971 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2972 ad1988_models, ad1988_cfg_tbl);
2973 if (board_config < 0) {
2974 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2975 board_config = AD1988_AUTO;
2978 if (board_config == AD1988_AUTO) {
2979 /* automatic parse from the BIOS config */
2980 err = ad1988_parse_auto_config(codec);
2985 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2986 board_config = AD1988_6STACK;
2990 err = snd_hda_attach_beep_device(codec, 0x10);
2995 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
2997 switch (board_config) {
2999 case AD1988_6STACK_DIG:
3000 spec->multiout.max_channels = 8;
3001 spec->multiout.num_dacs = 4;
3003 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3005 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3006 spec->input_mux = &ad1988_6stack_capture_source;
3007 spec->num_mixers = 2;
3009 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3011 spec->mixers[0] = ad1988_6stack_mixers1;
3012 spec->mixers[1] = ad1988_6stack_mixers2;
3013 spec->num_init_verbs = 1;
3014 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3015 if (board_config == AD1988_6STACK_DIG) {
3016 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3017 spec->dig_in_nid = AD1988_SPDIF_IN;
3021 case AD1988_3STACK_DIG:
3022 spec->multiout.max_channels = 6;
3023 spec->multiout.num_dacs = 3;
3025 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3027 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3028 spec->input_mux = &ad1988_6stack_capture_source;
3029 spec->channel_mode = ad1988_3stack_modes;
3030 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3031 spec->num_mixers = 2;
3033 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3035 spec->mixers[0] = ad1988_3stack_mixers1;
3036 spec->mixers[1] = ad1988_3stack_mixers2;
3037 spec->num_init_verbs = 1;
3038 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3039 if (board_config == AD1988_3STACK_DIG)
3040 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3043 case AD1988_LAPTOP_DIG:
3044 spec->multiout.max_channels = 2;
3045 spec->multiout.num_dacs = 1;
3046 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3047 spec->input_mux = &ad1988_laptop_capture_source;
3048 spec->num_mixers = 1;
3049 spec->mixers[0] = ad1988_laptop_mixers;
3050 spec->num_init_verbs = 1;
3051 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3052 if (board_config == AD1988_LAPTOP_DIG)
3053 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3057 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3058 spec->adc_nids = ad1988_adc_nids;
3059 spec->capsrc_nids = ad1988_capsrc_nids;
3060 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3061 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3062 if (spec->multiout.dig_out_nid) {
3063 if (codec->vendor_id >= 0x11d4989a) {
3064 spec->mixers[spec->num_mixers++] =
3065 ad1989_spdif_out_mixers;
3066 spec->init_verbs[spec->num_init_verbs++] =
3067 ad1989_spdif_init_verbs;
3068 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3070 spec->mixers[spec->num_mixers++] =
3071 ad1988_spdif_out_mixers;
3072 spec->init_verbs[spec->num_init_verbs++] =
3073 ad1988_spdif_init_verbs;
3076 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3077 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3079 codec->patch_ops = ad198x_patch_ops;
3080 switch (board_config) {
3082 codec->patch_ops.init = ad1988_auto_init;
3085 case AD1988_LAPTOP_DIG:
3086 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3089 #ifdef CONFIG_SND_HDA_POWER_SAVE
3090 spec->loopback.amplist = ad1988_loopbacks;
3092 spec->vmaster_nid = 0x04;
3101 * port-B - front line/mic-in
3102 * port-E - aux in/out
3103 * port-F - aux in/out
3104 * port-C - rear line/mic-in
3105 * port-D - rear line/hp-out
3106 * port-A - front line/hp-out
3108 * AD1984 = AD1884 + two digital mic-ins
3111 * For simplicity, we share the single DAC for both HP and line-outs
3112 * right now. The inidividual playbacks could be easily implemented,
3113 * but no build-up framework is given, so far.
3116 static hda_nid_t ad1884_dac_nids[1] = {
3120 static hda_nid_t ad1884_adc_nids[2] = {
3124 static hda_nid_t ad1884_capsrc_nids[2] = {
3128 #define AD1884_SPDIF_OUT 0x02
3130 static struct hda_input_mux ad1884_capture_source = {
3133 { "Front Mic", 0x0 },
3140 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3141 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3142 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3143 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3144 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3145 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3146 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3147 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3148 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3149 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3150 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3151 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3152 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3153 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3154 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3155 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3156 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3157 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3158 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3160 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3161 /* The multiple "Capture Source" controls confuse alsamixer
3162 * So call somewhat different..
3164 /* .name = "Capture Source", */
3165 .name = "Input Source",
3167 .info = ad198x_mux_enum_info,
3168 .get = ad198x_mux_enum_get,
3169 .put = ad198x_mux_enum_put,
3171 /* SPDIF controls */
3172 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3174 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3175 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3176 /* identical with ad1983 */
3177 .info = ad1983_spdif_route_info,
3178 .get = ad1983_spdif_route_get,
3179 .put = ad1983_spdif_route_put,
3184 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3185 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3186 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3187 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3189 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3195 * initialization verbs
3197 static struct hda_verb ad1884_init_verbs[] = {
3198 /* DACs; mute as default */
3199 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3200 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3201 /* Port-A (HP) mixer */
3202 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3203 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3205 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3206 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3207 /* HP selector - select DAC2 */
3208 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3209 /* Port-D (Line-out) mixer */
3210 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3211 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3213 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3214 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3215 /* Mono-out mixer */
3216 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3217 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3219 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3220 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3222 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3223 /* Port-B (front mic) pin */
3224 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3225 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3226 /* Port-C (rear mic) pin */
3227 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3228 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3229 /* Analog mixer; mute as default */
3230 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3231 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3232 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3233 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3234 /* Analog Mix output amp */
3235 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3236 /* SPDIF output selector */
3237 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3238 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3242 #ifdef CONFIG_SND_HDA_POWER_SAVE
3243 static struct hda_amp_list ad1884_loopbacks[] = {
3244 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3245 { 0x20, HDA_INPUT, 1 }, /* Mic */
3246 { 0x20, HDA_INPUT, 2 }, /* CD */
3247 { 0x20, HDA_INPUT, 4 }, /* Docking */
3252 static const char *ad1884_slave_vols[] = {
3253 "PCM Playback Volume",
3254 "Mic Playback Volume",
3255 "Mono Playback Volume",
3256 "Front Mic Playback Volume",
3257 "Mic Playback Volume",
3258 "CD Playback Volume",
3259 "Internal Mic Playback Volume",
3260 "Docking Mic Playback Volume"
3261 /* "Beep Playback Volume", */
3262 "IEC958 Playback Volume",
3266 static int patch_ad1884(struct hda_codec *codec)
3268 struct ad198x_spec *spec;
3271 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3277 err = snd_hda_attach_beep_device(codec, 0x10);
3282 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3284 spec->multiout.max_channels = 2;
3285 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3286 spec->multiout.dac_nids = ad1884_dac_nids;
3287 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3288 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3289 spec->adc_nids = ad1884_adc_nids;
3290 spec->capsrc_nids = ad1884_capsrc_nids;
3291 spec->input_mux = &ad1884_capture_source;
3292 spec->num_mixers = 1;
3293 spec->mixers[0] = ad1884_base_mixers;
3294 spec->num_init_verbs = 1;
3295 spec->init_verbs[0] = ad1884_init_verbs;
3296 spec->spdif_route = 0;
3297 #ifdef CONFIG_SND_HDA_POWER_SAVE
3298 spec->loopback.amplist = ad1884_loopbacks;
3300 spec->vmaster_nid = 0x04;
3301 /* we need to cover all playback volumes */
3302 spec->slave_vols = ad1884_slave_vols;
3304 codec->patch_ops = ad198x_patch_ops;
3310 * Lenovo Thinkpad T61/X61
3312 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3316 { "Internal Mic", 0x1 },
3318 { "Docking-Station", 0x4 },
3324 * Dell Precision T3400
3326 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3329 { "Front Mic", 0x0 },
3336 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3337 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3338 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3339 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3340 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3341 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3342 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3343 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3344 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3345 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3346 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3347 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3348 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3349 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3350 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3351 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3352 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3353 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3355 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3356 /* The multiple "Capture Source" controls confuse alsamixer
3357 * So call somewhat different..
3359 /* .name = "Capture Source", */
3360 .name = "Input Source",
3362 .info = ad198x_mux_enum_info,
3363 .get = ad198x_mux_enum_get,
3364 .put = ad198x_mux_enum_put,
3366 /* SPDIF controls */
3367 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3369 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3370 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3371 /* identical with ad1983 */
3372 .info = ad1983_spdif_route_info,
3373 .get = ad1983_spdif_route_get,
3374 .put = ad1983_spdif_route_put,
3379 /* additional verbs */
3380 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3381 /* Port-E (docking station mic) pin */
3382 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3383 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3384 /* docking mic boost */
3385 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3386 /* Analog mixer - docking mic; mute as default */
3387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3388 /* enable EAPD bit */
3389 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3394 * Dell Precision T3400
3396 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3397 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3398 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3399 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3400 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3401 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3402 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3403 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3404 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3405 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3406 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3407 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3408 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3409 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3410 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3411 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3413 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3414 /* The multiple "Capture Source" controls confuse alsamixer
3415 * So call somewhat different..
3417 /* .name = "Capture Source", */
3418 .name = "Input Source",
3420 .info = ad198x_mux_enum_info,
3421 .get = ad198x_mux_enum_get,
3422 .put = ad198x_mux_enum_put,
3427 /* Digial MIC ADC NID 0x05 + 0x06 */
3428 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3429 struct hda_codec *codec,
3430 unsigned int stream_tag,
3431 unsigned int format,
3432 struct snd_pcm_substream *substream)
3434 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3435 stream_tag, 0, format);
3439 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3440 struct hda_codec *codec,
3441 struct snd_pcm_substream *substream)
3443 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3447 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3453 .prepare = ad1984_pcm_dmic_prepare,
3454 .cleanup = ad1984_pcm_dmic_cleanup
3458 static int ad1984_build_pcms(struct hda_codec *codec)
3460 struct ad198x_spec *spec = codec->spec;
3461 struct hda_pcm *info;
3464 err = ad198x_build_pcms(codec);
3468 info = spec->pcm_rec + codec->num_pcms;
3470 info->name = "AD1984 Digital Mic";
3471 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3479 AD1984_DELL_DESKTOP,
3483 static const char *ad1984_models[AD1984_MODELS] = {
3484 [AD1984_BASIC] = "basic",
3485 [AD1984_THINKPAD] = "thinkpad",
3486 [AD1984_DELL_DESKTOP] = "dell_desktop",
3489 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3490 /* Lenovo Thinkpad T61/X61 */
3491 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3492 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3496 static int patch_ad1984(struct hda_codec *codec)
3498 struct ad198x_spec *spec;
3499 int board_config, err;
3501 err = patch_ad1884(codec);
3505 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3506 ad1984_models, ad1984_cfg_tbl);
3507 switch (board_config) {
3509 /* additional digital mics */
3510 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3511 codec->patch_ops.build_pcms = ad1984_build_pcms;
3513 case AD1984_THINKPAD:
3514 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3515 spec->input_mux = &ad1984_thinkpad_capture_source;
3516 spec->mixers[0] = ad1984_thinkpad_mixers;
3517 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3519 case AD1984_DELL_DESKTOP:
3520 spec->multiout.dig_out_nid = 0;
3521 spec->input_mux = &ad1984_dell_desktop_capture_source;
3522 spec->mixers[0] = ad1984_dell_desktop_mixers;
3530 * AD1883 / AD1884A / AD1984A / AD1984B
3532 * port-B (0x14) - front mic-in
3533 * port-E (0x1c) - rear mic-in
3534 * port-F (0x16) - CD / ext out
3535 * port-C (0x15) - rear line-in
3536 * port-D (0x12) - rear line-out
3537 * port-A (0x11) - front hp-out
3539 * AD1984A = AD1884A + digital-mic
3540 * AD1883 = equivalent with AD1984A
3541 * AD1984B = AD1984A + extra SPDIF-out
3544 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3547 static hda_nid_t ad1884a_dac_nids[1] = {
3551 #define ad1884a_adc_nids ad1884_adc_nids
3552 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3554 #define AD1884A_SPDIF_OUT 0x02
3556 static struct hda_input_mux ad1884a_capture_source = {
3559 { "Front Mic", 0x0 },
3567 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3568 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3569 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3570 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3571 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3572 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3573 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3574 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3575 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3576 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3577 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3578 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3579 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3580 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3581 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3582 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3583 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3584 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3585 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3586 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3587 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3588 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3589 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3590 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3593 /* The multiple "Capture Source" controls confuse alsamixer
3594 * So call somewhat different..
3596 /* .name = "Capture Source", */
3597 .name = "Input Source",
3599 .info = ad198x_mux_enum_info,
3600 .get = ad198x_mux_enum_get,
3601 .put = ad198x_mux_enum_put,
3603 /* SPDIF controls */
3604 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3606 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3607 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3608 /* identical with ad1983 */
3609 .info = ad1983_spdif_route_info,
3610 .get = ad1983_spdif_route_get,
3611 .put = ad1983_spdif_route_put,
3617 * initialization verbs
3619 static struct hda_verb ad1884a_init_verbs[] = {
3620 /* DACs; unmute as default */
3621 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3622 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3623 /* Port-A (HP) mixer - route only from analog mixer */
3624 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3625 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3627 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3628 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3629 /* Port-D (Line-out) mixer - route only from analog mixer */
3630 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3631 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3633 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3634 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3635 /* Mono-out mixer - route only from analog mixer */
3636 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3637 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3639 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3640 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3641 /* Port-B (front mic) pin */
3642 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3643 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3644 /* Port-C (rear line-in) pin */
3645 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3646 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3647 /* Port-E (rear mic) pin */
3648 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3649 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3650 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3651 /* Port-F (CD) pin */
3652 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3653 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3654 /* Analog mixer; mute as default */
3655 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3656 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3657 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3658 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3659 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3660 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3661 /* Analog Mix output amp */
3662 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3663 /* capture sources */
3664 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3665 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3666 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3667 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3668 /* SPDIF output amp */
3669 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3673 #ifdef CONFIG_SND_HDA_POWER_SAVE
3674 static struct hda_amp_list ad1884a_loopbacks[] = {
3675 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3676 { 0x20, HDA_INPUT, 1 }, /* Mic */
3677 { 0x20, HDA_INPUT, 2 }, /* CD */
3678 { 0x20, HDA_INPUT, 4 }, /* Docking */
3686 * Port A: Headphone jack
3688 * Port C: Internal MIC
3689 * Port D: Dock Line Out (if enabled)
3690 * Port E: Dock Line In (if enabled)
3691 * Port F: Internal speakers
3694 static struct hda_input_mux ad1884a_laptop_capture_source = {
3697 { "Mic", 0x0 }, /* port-B */
3698 { "Internal Mic", 0x1 }, /* port-C */
3699 { "Dock Mic", 0x4 }, /* port-E */
3704 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3705 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3706 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3707 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3708 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3709 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3710 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3711 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3712 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3713 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3714 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3715 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3716 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3717 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3718 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3719 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3720 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3721 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3722 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3725 /* The multiple "Capture Source" controls confuse alsamixer
3726 * So call somewhat different..
3728 /* .name = "Capture Source", */
3729 .name = "Input Source",
3731 .info = ad198x_mux_enum_info,
3732 .get = ad198x_mux_enum_get,
3733 .put = ad198x_mux_enum_put,
3738 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3739 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3740 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3741 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3742 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3743 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3744 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3745 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3746 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3750 /* mute internal speaker if HP is plugged */
3751 static void ad1884a_hp_automute(struct hda_codec *codec)
3753 unsigned int present;
3755 present = snd_hda_codec_read(codec, 0x11, 0,
3756 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3757 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3758 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3759 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3760 present ? 0x00 : 0x02);
3763 /* switch to external mic if plugged */
3764 static void ad1884a_hp_automic(struct hda_codec *codec)
3766 unsigned int present;
3768 present = snd_hda_codec_read(codec, 0x14, 0,
3769 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3770 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3774 #define AD1884A_HP_EVENT 0x37
3775 #define AD1884A_MIC_EVENT 0x36
3777 /* unsolicited event for HP jack sensing */
3778 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3780 switch (res >> 26) {
3781 case AD1884A_HP_EVENT:
3782 ad1884a_hp_automute(codec);
3784 case AD1884A_MIC_EVENT:
3785 ad1884a_hp_automic(codec);
3790 /* initialize jack-sensing, too */
3791 static int ad1884a_hp_init(struct hda_codec *codec)
3794 ad1884a_hp_automute(codec);
3795 ad1884a_hp_automic(codec);
3799 /* additional verbs for laptop model */
3800 static struct hda_verb ad1884a_laptop_verbs[] = {
3801 /* Port-A (HP) pin - always unmuted */
3802 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3803 /* Port-F (int speaker) mixer - route only from analog mixer */
3804 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3805 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3807 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3808 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3809 /* Port-C pin - internal mic-in */
3810 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3811 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3812 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3814 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3815 /* unsolicited event for pin-sense */
3816 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3817 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3826 * 0x17 - built-in mic
3829 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3831 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3833 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3835 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3836 /* unsolicited event for pin-sense */
3837 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3838 /* internal mic - dmic */
3839 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3840 /* set magic COEFs for dmic */
3841 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3842 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
3846 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3847 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3848 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3849 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3850 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3851 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3852 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3853 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3854 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3855 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3856 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3858 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3859 .name = "Capture Source",
3860 .info = ad198x_mux_enum_info,
3861 .get = ad198x_mux_enum_get,
3862 .put = ad198x_mux_enum_put,
3867 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
3871 { "Internal Mic", 0x5 },
3876 /* mute internal speaker if HP is plugged */
3877 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
3879 unsigned int present;
3881 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
3882 & AC_PINSENSE_PRESENCE;
3883 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
3884 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3887 /* unsolicited event for HP jack sensing */
3888 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
3891 if ((res >> 26) != AD1884A_HP_EVENT)
3893 ad1984a_thinkpad_automute(codec);
3896 /* initialize jack-sensing, too */
3897 static int ad1984a_thinkpad_init(struct hda_codec *codec)
3900 ad1984a_thinkpad_automute(codec);
3915 static const char *ad1884a_models[AD1884A_MODELS] = {
3916 [AD1884A_DESKTOP] = "desktop",
3917 [AD1884A_LAPTOP] = "laptop",
3918 [AD1884A_MOBILE] = "mobile",
3919 [AD1884A_THINKPAD] = "thinkpad",
3922 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3923 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
3924 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
3925 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
3926 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
3927 SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
3928 SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
3929 SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
3930 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
3934 static int patch_ad1884a(struct hda_codec *codec)
3936 struct ad198x_spec *spec;
3937 int err, board_config;
3939 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3945 err = snd_hda_attach_beep_device(codec, 0x10);
3950 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3952 spec->multiout.max_channels = 2;
3953 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3954 spec->multiout.dac_nids = ad1884a_dac_nids;
3955 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3956 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3957 spec->adc_nids = ad1884a_adc_nids;
3958 spec->capsrc_nids = ad1884a_capsrc_nids;
3959 spec->input_mux = &ad1884a_capture_source;
3960 spec->num_mixers = 1;
3961 spec->mixers[0] = ad1884a_base_mixers;
3962 spec->num_init_verbs = 1;
3963 spec->init_verbs[0] = ad1884a_init_verbs;
3964 spec->spdif_route = 0;
3965 #ifdef CONFIG_SND_HDA_POWER_SAVE
3966 spec->loopback.amplist = ad1884a_loopbacks;
3968 codec->patch_ops = ad198x_patch_ops;
3970 /* override some parameters */
3971 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
3974 switch (board_config) {
3975 case AD1884A_LAPTOP:
3976 spec->mixers[0] = ad1884a_laptop_mixers;
3977 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3978 spec->multiout.dig_out_nid = 0;
3979 spec->input_mux = &ad1884a_laptop_capture_source;
3980 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3981 codec->patch_ops.init = ad1884a_hp_init;
3983 case AD1884A_MOBILE:
3984 spec->mixers[0] = ad1884a_mobile_mixers;
3985 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3986 spec->multiout.dig_out_nid = 0;
3987 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3988 codec->patch_ops.init = ad1884a_hp_init;
3990 case AD1884A_THINKPAD:
3991 spec->mixers[0] = ad1984a_thinkpad_mixers;
3992 spec->init_verbs[spec->num_init_verbs++] =
3993 ad1984a_thinkpad_verbs;
3994 spec->multiout.dig_out_nid = 0;
3995 spec->input_mux = &ad1984a_thinkpad_capture_source;
3996 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
3997 codec->patch_ops.init = ad1984a_thinkpad_init;
4008 * port-A - front hp-out
4009 * port-B - front mic-in
4010 * port-C - rear line-in, shared surr-out (3stack)
4011 * port-D - rear line-out
4012 * port-E - rear mic-in, shared clfe-out (3stack)
4013 * port-F - rear surr-out (6stack)
4014 * port-G - rear clfe-out (6stack)
4017 static hda_nid_t ad1882_dac_nids[3] = {
4021 static hda_nid_t ad1882_adc_nids[2] = {
4025 static hda_nid_t ad1882_capsrc_nids[2] = {
4029 #define AD1882_SPDIF_OUT 0x02
4031 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4032 static struct hda_input_mux ad1882_capture_source = {
4035 { "Front Mic", 0x1 },
4043 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4044 static struct hda_input_mux ad1882a_capture_source = {
4047 { "Front Mic", 0x1 },
4050 { "Digital Mic", 0x06 },
4055 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4056 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4057 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4058 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4059 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4060 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4061 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4062 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4063 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4065 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4066 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4067 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4068 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4069 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4070 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4071 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4073 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4074 /* The multiple "Capture Source" controls confuse alsamixer
4075 * So call somewhat different..
4077 /* .name = "Capture Source", */
4078 .name = "Input Source",
4080 .info = ad198x_mux_enum_info,
4081 .get = ad198x_mux_enum_get,
4082 .put = ad198x_mux_enum_put,
4084 /* SPDIF controls */
4085 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4087 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4088 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4089 /* identical with ad1983 */
4090 .info = ad1983_spdif_route_info,
4091 .get = ad1983_spdif_route_get,
4092 .put = ad1983_spdif_route_put,
4097 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4098 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4099 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4100 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4101 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4102 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4103 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4104 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4105 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4109 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4110 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4111 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4112 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4113 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4114 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4115 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4116 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4117 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4118 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4122 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4123 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4124 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4125 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4127 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4128 .name = "Channel Mode",
4129 .info = ad198x_ch_mode_info,
4130 .get = ad198x_ch_mode_get,
4131 .put = ad198x_ch_mode_put,
4136 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4137 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4138 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4139 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4143 static struct hda_verb ad1882_ch2_init[] = {
4144 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
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 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4148 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4149 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4153 static struct hda_verb ad1882_ch4_init[] = {
4154 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4155 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4156 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4157 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4158 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4159 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4163 static struct hda_verb ad1882_ch6_init[] = {
4164 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4165 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4166 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4167 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4168 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4169 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4173 static struct hda_channel_mode ad1882_modes[3] = {
4174 { 2, ad1882_ch2_init },
4175 { 4, ad1882_ch4_init },
4176 { 6, ad1882_ch6_init },
4180 * initialization verbs
4182 static struct hda_verb ad1882_init_verbs[] = {
4183 /* DACs; mute as default */
4184 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4185 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4186 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4187 /* Port-A (HP) mixer */
4188 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4189 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4191 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4192 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4193 /* HP selector - select DAC2 */
4194 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4195 /* Port-D (Line-out) mixer */
4196 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4197 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4199 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4200 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4201 /* Mono-out mixer */
4202 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4203 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4205 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4206 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4207 /* Port-B (front mic) pin */
4208 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4209 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4210 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4211 /* Port-C (line-in) pin */
4212 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4213 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4214 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4215 /* Port-C mixer - mute as input */
4216 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4217 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4218 /* Port-E (mic-in) pin */
4219 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4220 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4221 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4222 /* Port-E mixer - mute as input */
4223 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4224 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4225 /* Port-F (surround) */
4226 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4227 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4229 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4230 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4231 /* Analog mixer; mute as default */
4232 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4233 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4234 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4235 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4236 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4237 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4238 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4239 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4240 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4241 /* Analog Mix output amp */
4242 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4243 /* SPDIF output selector */
4244 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4245 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4246 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4250 #ifdef CONFIG_SND_HDA_POWER_SAVE
4251 static struct hda_amp_list ad1882_loopbacks[] = {
4252 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4253 { 0x20, HDA_INPUT, 1 }, /* Mic */
4254 { 0x20, HDA_INPUT, 4 }, /* Line */
4255 { 0x20, HDA_INPUT, 6 }, /* CD */
4267 static const char *ad1882_models[AD1986A_MODELS] = {
4268 [AD1882_3STACK] = "3stack",
4269 [AD1882_6STACK] = "6stack",
4273 static int patch_ad1882(struct hda_codec *codec)
4275 struct ad198x_spec *spec;
4276 int err, board_config;
4278 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4284 err = snd_hda_attach_beep_device(codec, 0x10);
4289 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4291 spec->multiout.max_channels = 6;
4292 spec->multiout.num_dacs = 3;
4293 spec->multiout.dac_nids = ad1882_dac_nids;
4294 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4295 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4296 spec->adc_nids = ad1882_adc_nids;
4297 spec->capsrc_nids = ad1882_capsrc_nids;
4298 if (codec->vendor_id == 0x11d41882)
4299 spec->input_mux = &ad1882_capture_source;
4301 spec->input_mux = &ad1882a_capture_source;
4302 spec->num_mixers = 2;
4303 spec->mixers[0] = ad1882_base_mixers;
4304 if (codec->vendor_id == 0x11d41882)
4305 spec->mixers[1] = ad1882_loopback_mixers;
4307 spec->mixers[1] = ad1882a_loopback_mixers;
4308 spec->num_init_verbs = 1;
4309 spec->init_verbs[0] = ad1882_init_verbs;
4310 spec->spdif_route = 0;
4311 #ifdef CONFIG_SND_HDA_POWER_SAVE
4312 spec->loopback.amplist = ad1882_loopbacks;
4314 spec->vmaster_nid = 0x04;
4316 codec->patch_ops = ad198x_patch_ops;
4318 /* override some parameters */
4319 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4320 ad1882_models, NULL);
4321 switch (board_config) {
4324 spec->num_mixers = 3;
4325 spec->mixers[2] = ad1882_3stack_mixers;
4326 spec->channel_mode = ad1882_modes;
4327 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4328 spec->need_dac_fix = 1;
4329 spec->multiout.max_channels = 2;
4330 spec->multiout.num_dacs = 1;
4333 spec->num_mixers = 3;
4334 spec->mixers[2] = ad1882_6stack_mixers;
4344 static struct hda_codec_preset snd_hda_preset_analog[] = {
4345 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4346 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4347 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4348 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4349 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4350 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4351 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4352 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4353 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4354 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4355 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4356 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4357 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4358 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4359 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4363 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4365 MODULE_LICENSE("GPL");
4366 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4368 static struct hda_codec_preset_list analog_list = {
4369 .preset = snd_hda_preset_analog,
4370 .owner = THIS_MODULE,
4373 static int __init patch_analog_init(void)
4375 return snd_hda_add_codec_preset(&analog_list);
4378 static void __exit patch_analog_exit(void)
4380 snd_hda_delete_codec_preset(&analog_list);
4383 module_init(patch_analog_init)
4384 module_exit(patch_analog_exit)