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_get_pincfg(codec, nid);
1051 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1054 static int patch_ad1986a(struct hda_codec *codec)
1056 struct ad198x_spec *spec;
1057 int err, board_config;
1059 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1065 err = snd_hda_attach_beep_device(codec, 0x19);
1070 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1072 spec->multiout.max_channels = 6;
1073 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1074 spec->multiout.dac_nids = ad1986a_dac_nids;
1075 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1076 spec->num_adc_nids = 1;
1077 spec->adc_nids = ad1986a_adc_nids;
1078 spec->capsrc_nids = ad1986a_capsrc_nids;
1079 spec->input_mux = &ad1986a_capture_source;
1080 spec->num_mixers = 1;
1081 spec->mixers[0] = ad1986a_mixers;
1082 spec->num_init_verbs = 1;
1083 spec->init_verbs[0] = ad1986a_init_verbs;
1084 #ifdef CONFIG_SND_HDA_POWER_SAVE
1085 spec->loopback.amplist = ad1986a_loopbacks;
1087 spec->vmaster_nid = 0x1b;
1089 codec->patch_ops = ad198x_patch_ops;
1091 /* override some parameters */
1092 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1095 switch (board_config) {
1096 case AD1986A_3STACK:
1097 spec->num_mixers = 2;
1098 spec->mixers[1] = ad1986a_3st_mixers;
1099 spec->num_init_verbs = 2;
1100 spec->init_verbs[1] = ad1986a_ch2_init;
1101 spec->channel_mode = ad1986a_modes;
1102 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1103 spec->need_dac_fix = 1;
1104 spec->multiout.max_channels = 2;
1105 spec->multiout.num_dacs = 1;
1107 case AD1986A_LAPTOP:
1108 spec->mixers[0] = ad1986a_laptop_mixers;
1109 spec->multiout.max_channels = 2;
1110 spec->multiout.num_dacs = 1;
1111 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1113 case AD1986A_LAPTOP_EAPD:
1114 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1115 spec->num_init_verbs = 2;
1116 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1117 spec->multiout.max_channels = 2;
1118 spec->multiout.num_dacs = 1;
1119 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1120 if (!is_jack_available(codec, 0x25))
1121 spec->multiout.dig_out_nid = 0;
1122 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1124 case AD1986A_SAMSUNG:
1125 spec->mixers[0] = ad1986a_samsung_mixers;
1126 spec->num_init_verbs = 3;
1127 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1128 spec->init_verbs[2] = ad1986a_automic_verbs;
1129 spec->multiout.max_channels = 2;
1130 spec->multiout.num_dacs = 1;
1131 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1132 if (!is_jack_available(codec, 0x25))
1133 spec->multiout.dig_out_nid = 0;
1134 spec->input_mux = &ad1986a_automic_capture_source;
1135 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1136 codec->patch_ops.init = ad1986a_automic_init;
1138 case AD1986A_LAPTOP_AUTOMUTE:
1139 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1140 spec->num_init_verbs = 3;
1141 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1142 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1143 spec->multiout.max_channels = 2;
1144 spec->multiout.num_dacs = 1;
1145 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1146 if (!is_jack_available(codec, 0x25))
1147 spec->multiout.dig_out_nid = 0;
1148 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1149 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1150 codec->patch_ops.init = ad1986a_hp_init;
1153 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1154 spec->num_init_verbs = 2;
1155 spec->init_verbs[1] = ad1986a_ultra_init;
1156 spec->multiout.max_channels = 2;
1157 spec->multiout.num_dacs = 1;
1158 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1159 spec->multiout.dig_out_nid = 0;
1163 /* AD1986A has a hardware problem that it can't share a stream
1164 * with multiple output pins. The copy of front to surrounds
1165 * causes noisy or silent outputs at a certain timing, e.g.
1166 * changing the volume.
1167 * So, let's disable the shared stream.
1169 spec->multiout.no_share_stream = 1;
1178 #define AD1983_SPDIF_OUT 0x02
1179 #define AD1983_DAC 0x03
1180 #define AD1983_ADC 0x04
1182 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1183 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1184 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1186 static struct hda_input_mux ad1983_capture_source = {
1192 { "Mix Mono", 0x3 },
1197 * SPDIF playback route
1199 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1201 static char *texts[] = { "PCM", "ADC" };
1203 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1205 uinfo->value.enumerated.items = 2;
1206 if (uinfo->value.enumerated.item > 1)
1207 uinfo->value.enumerated.item = 1;
1208 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1212 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1214 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1215 struct ad198x_spec *spec = codec->spec;
1217 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1221 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1223 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1224 struct ad198x_spec *spec = codec->spec;
1226 if (ucontrol->value.enumerated.item[0] > 1)
1228 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1229 spec->spdif_route = ucontrol->value.enumerated.item[0];
1230 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1231 AC_VERB_SET_CONNECT_SEL,
1238 static struct snd_kcontrol_new ad1983_mixers[] = {
1239 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1240 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1241 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1242 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1243 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1244 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1245 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1246 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1247 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1248 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1249 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1250 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1251 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1252 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1253 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1256 .name = "Capture Source",
1257 .info = ad198x_mux_enum_info,
1258 .get = ad198x_mux_enum_get,
1259 .put = ad198x_mux_enum_put,
1262 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1263 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1264 .info = ad1983_spdif_route_info,
1265 .get = ad1983_spdif_route_get,
1266 .put = ad1983_spdif_route_put,
1271 static struct hda_verb ad1983_init_verbs[] = {
1272 /* Front, HP, Mono; mute as default */
1273 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1274 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1275 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1276 /* Beep, PCM, Mic, Line-In: mute */
1277 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1278 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1279 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1280 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1281 /* Front, HP selectors; from Mix */
1282 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1283 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1284 /* Mono selector; from Mix */
1285 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1286 /* Mic selector; Mic */
1287 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1288 /* Line-in selector: Line-in */
1289 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1290 /* Mic boost: 0dB */
1291 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1292 /* Record selector: mic */
1293 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1294 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1295 /* SPDIF route: PCM */
1296 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1298 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1300 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1302 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1304 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1306 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1310 #ifdef CONFIG_SND_HDA_POWER_SAVE
1311 static struct hda_amp_list ad1983_loopbacks[] = {
1312 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1313 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1318 static int patch_ad1983(struct hda_codec *codec)
1320 struct ad198x_spec *spec;
1323 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1329 err = snd_hda_attach_beep_device(codec, 0x10);
1334 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1336 spec->multiout.max_channels = 2;
1337 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1338 spec->multiout.dac_nids = ad1983_dac_nids;
1339 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1340 spec->num_adc_nids = 1;
1341 spec->adc_nids = ad1983_adc_nids;
1342 spec->capsrc_nids = ad1983_capsrc_nids;
1343 spec->input_mux = &ad1983_capture_source;
1344 spec->num_mixers = 1;
1345 spec->mixers[0] = ad1983_mixers;
1346 spec->num_init_verbs = 1;
1347 spec->init_verbs[0] = ad1983_init_verbs;
1348 spec->spdif_route = 0;
1349 #ifdef CONFIG_SND_HDA_POWER_SAVE
1350 spec->loopback.amplist = ad1983_loopbacks;
1352 spec->vmaster_nid = 0x05;
1354 codec->patch_ops = ad198x_patch_ops;
1361 * AD1981 HD specific
1364 #define AD1981_SPDIF_OUT 0x02
1365 #define AD1981_DAC 0x03
1366 #define AD1981_ADC 0x04
1368 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1369 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1370 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1372 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1373 static struct hda_input_mux ad1981_capture_source = {
1376 { "Front Mic", 0x0 },
1379 { "Mix Mono", 0x3 },
1386 static struct snd_kcontrol_new ad1981_mixers[] = {
1387 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1388 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1389 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1390 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1391 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1392 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1393 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1394 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1395 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1396 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1397 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1398 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1399 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1400 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1401 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1402 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1403 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1404 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1405 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1406 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1407 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1408 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1411 .name = "Capture Source",
1412 .info = ad198x_mux_enum_info,
1413 .get = ad198x_mux_enum_get,
1414 .put = ad198x_mux_enum_put,
1416 /* identical with AD1983 */
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1420 .info = ad1983_spdif_route_info,
1421 .get = ad1983_spdif_route_get,
1422 .put = ad1983_spdif_route_put,
1427 static struct hda_verb ad1981_init_verbs[] = {
1428 /* Front, HP, Mono; mute as default */
1429 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1430 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1431 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1432 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1433 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1434 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1435 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1436 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1437 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1438 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1439 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1440 /* Front, HP selectors; from Mix */
1441 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1442 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1443 /* Mono selector; from Mix */
1444 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1445 /* Mic Mixer; select Front Mic */
1446 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1447 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1448 /* Mic boost: 0dB */
1449 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1450 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1451 /* Record selector: Front mic */
1452 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1453 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1454 /* SPDIF route: PCM */
1455 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1457 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1459 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1461 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1462 /* Front & Rear Mic Pins */
1463 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1464 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1466 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1468 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1469 /* Line-Out as Input: disabled */
1470 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1474 #ifdef CONFIG_SND_HDA_POWER_SAVE
1475 static struct hda_amp_list ad1981_loopbacks[] = {
1476 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1477 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1478 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1479 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1480 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1486 * Patch for HP nx6320
1488 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1489 * speaker output enabled _and_ mute-LED off.
1492 #define AD1981_HP_EVENT 0x37
1493 #define AD1981_MIC_EVENT 0x38
1495 static struct hda_verb ad1981_hp_init_verbs[] = {
1496 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1497 /* pin sensing on HP and Mic jacks */
1498 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1499 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1503 /* turn on/off EAPD (+ mute HP) as a master switch */
1504 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1505 struct snd_ctl_elem_value *ucontrol)
1507 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1508 struct ad198x_spec *spec = codec->spec;
1510 if (! ad198x_eapd_put(kcontrol, ucontrol))
1512 /* change speaker pin appropriately */
1513 snd_hda_codec_write(codec, 0x05, 0,
1514 AC_VERB_SET_PIN_WIDGET_CONTROL,
1515 spec->cur_eapd ? PIN_OUT : 0);
1516 /* toggle HP mute appropriately */
1517 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1519 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1523 /* bind volumes of both NID 0x05 and 0x06 */
1524 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1525 .ops = &snd_hda_bind_vol,
1527 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1528 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1533 /* mute internal speaker if HP is plugged */
1534 static void ad1981_hp_automute(struct hda_codec *codec)
1536 unsigned int present;
1538 present = snd_hda_codec_read(codec, 0x06, 0,
1539 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1540 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1541 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1544 /* toggle input of built-in and mic jack appropriately */
1545 static void ad1981_hp_automic(struct hda_codec *codec)
1547 static struct hda_verb mic_jack_on[] = {
1548 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1549 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1552 static struct hda_verb mic_jack_off[] = {
1553 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1554 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1557 unsigned int present;
1559 present = snd_hda_codec_read(codec, 0x08, 0,
1560 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1562 snd_hda_sequence_write(codec, mic_jack_on);
1564 snd_hda_sequence_write(codec, mic_jack_off);
1567 /* unsolicited event for HP jack sensing */
1568 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1573 case AD1981_HP_EVENT:
1574 ad1981_hp_automute(codec);
1576 case AD1981_MIC_EVENT:
1577 ad1981_hp_automic(codec);
1582 static struct hda_input_mux ad1981_hp_capture_source = {
1586 { "Docking-Station", 0x1 },
1591 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1592 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1594 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595 .name = "Master Playback Switch",
1596 .info = ad198x_eapd_info,
1597 .get = ad198x_eapd_get,
1598 .put = ad1981_hp_master_sw_put,
1599 .private_value = 0x05,
1601 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1602 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1604 /* FIXME: analog mic/line loopback doesn't work with my tests...
1605 * (although recording is OK)
1607 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1608 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1609 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1610 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1611 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1612 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1613 /* FIXME: does this laptop have analog CD connection? */
1614 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1615 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1617 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1618 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1619 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1620 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1622 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1623 .name = "Capture Source",
1624 .info = ad198x_mux_enum_info,
1625 .get = ad198x_mux_enum_get,
1626 .put = ad198x_mux_enum_put,
1631 /* initialize jack-sensing, too */
1632 static int ad1981_hp_init(struct hda_codec *codec)
1635 ad1981_hp_automute(codec);
1636 ad1981_hp_automic(codec);
1640 /* configuration for Toshiba Laptops */
1641 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1642 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1643 /* pin sensing on HP and Mic jacks */
1644 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1645 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1649 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1650 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1651 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1655 /* configuration for Lenovo Thinkpad T60 */
1656 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1657 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1658 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1659 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1660 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1661 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1662 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1663 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1664 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1665 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1666 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1667 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1669 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1670 .name = "Capture Source",
1671 .info = ad198x_mux_enum_info,
1672 .get = ad198x_mux_enum_get,
1673 .put = ad198x_mux_enum_put,
1675 /* identical with AD1983 */
1677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1678 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1679 .info = ad1983_spdif_route_info,
1680 .get = ad1983_spdif_route_get,
1681 .put = ad1983_spdif_route_put,
1686 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1704 static const char *ad1981_models[AD1981_MODELS] = {
1706 [AD1981_THINKPAD] = "thinkpad",
1707 [AD1981_BASIC] = "basic",
1708 [AD1981_TOSHIBA] = "toshiba"
1711 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1712 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1713 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1715 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1716 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1717 /* Lenovo Thinkpad T60/X60/Z6xx */
1718 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1719 /* HP nx6320 (reversed SSID, H/W bug) */
1720 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1724 static int patch_ad1981(struct hda_codec *codec)
1726 struct ad198x_spec *spec;
1727 int err, board_config;
1729 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1735 err = snd_hda_attach_beep_device(codec, 0x10);
1740 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1742 spec->multiout.max_channels = 2;
1743 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1744 spec->multiout.dac_nids = ad1981_dac_nids;
1745 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1746 spec->num_adc_nids = 1;
1747 spec->adc_nids = ad1981_adc_nids;
1748 spec->capsrc_nids = ad1981_capsrc_nids;
1749 spec->input_mux = &ad1981_capture_source;
1750 spec->num_mixers = 1;
1751 spec->mixers[0] = ad1981_mixers;
1752 spec->num_init_verbs = 1;
1753 spec->init_verbs[0] = ad1981_init_verbs;
1754 spec->spdif_route = 0;
1755 #ifdef CONFIG_SND_HDA_POWER_SAVE
1756 spec->loopback.amplist = ad1981_loopbacks;
1758 spec->vmaster_nid = 0x05;
1760 codec->patch_ops = ad198x_patch_ops;
1762 /* override some parameters */
1763 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1766 switch (board_config) {
1768 spec->mixers[0] = ad1981_hp_mixers;
1769 spec->num_init_verbs = 2;
1770 spec->init_verbs[1] = ad1981_hp_init_verbs;
1771 spec->multiout.dig_out_nid = 0;
1772 spec->input_mux = &ad1981_hp_capture_source;
1774 codec->patch_ops.init = ad1981_hp_init;
1775 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1777 case AD1981_THINKPAD:
1778 spec->mixers[0] = ad1981_thinkpad_mixers;
1779 spec->input_mux = &ad1981_thinkpad_capture_source;
1781 case AD1981_TOSHIBA:
1782 spec->mixers[0] = ad1981_hp_mixers;
1783 spec->mixers[1] = ad1981_toshiba_mixers;
1784 spec->num_init_verbs = 2;
1785 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1786 spec->multiout.dig_out_nid = 0;
1787 spec->input_mux = &ad1981_hp_capture_source;
1788 codec->patch_ops.init = ad1981_hp_init;
1789 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1799 * Output pins and routes
1801 * Pin Mix Sel DAC (*)
1802 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1803 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1804 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1805 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1806 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1807 * port-F 0x16 (mute) <- 0x2a <- 06
1808 * port-G 0x24 (mute) <- 0x27 <- 05
1809 * port-H 0x25 (mute) <- 0x28 <- 0a
1810 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1812 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1813 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1815 * Input pins and routes
1817 * pin boost mix input # / adc input #
1818 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1819 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1820 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1821 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1822 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1823 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1824 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1825 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1829 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1830 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1832 * Inputs of Analog Mix (0x20)
1833 * 0:Port-B (front mic)
1834 * 1:Port-C/G/H (line-in)
1836 * 3:Port-D (line-in/2)
1837 * 4:Port-E/G/H (mic-in)
1838 * 5:Port-F (mic2-in)
1844 * 1:Port-B (front mic-in)
1845 * 2:Port-C (line-in)
1846 * 3:Port-F (mic2-in)
1851 * 8:Port-D (line-in/2)
1854 * Proposed pin assignments by the datasheet
1857 * Port-A front headphone
1867 * Port-A front headphone
1869 * C rear line-in/surround
1871 * E rear mic-in/CLFE
1877 * D internal speaker (with EAPD)
1878 * E/F quad mic array
1894 /* reivision id to check workarounds */
1895 #define AD1988A_REV2 0x100200
1897 #define is_rev2(codec) \
1898 ((codec)->vendor_id == 0x11d41988 && \
1899 (codec)->revision_id == AD1988A_REV2)
1905 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1906 0x04, 0x06, 0x05, 0x0a
1909 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1913 /* for AD1988A revision-2, DAC2-4 are swapped */
1914 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1915 0x04, 0x05, 0x0a, 0x06
1918 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1922 static hda_nid_t ad1988_adc_nids[3] = {
1926 static hda_nid_t ad1988_capsrc_nids[3] = {
1930 #define AD1988_SPDIF_OUT 0x02
1931 #define AD1988_SPDIF_OUT_HDMI 0x0b
1932 #define AD1988_SPDIF_IN 0x07
1934 static hda_nid_t ad1989b_slave_dig_outs[] = {
1935 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
1938 static struct hda_input_mux ad1988_6stack_capture_source = {
1941 { "Front Mic", 0x1 }, /* port-B */
1942 { "Line", 0x2 }, /* port-C */
1943 { "Mic", 0x4 }, /* port-E */
1949 static struct hda_input_mux ad1988_laptop_capture_source = {
1952 { "Mic/Line", 0x1 }, /* port-B */
1960 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1961 struct snd_ctl_elem_info *uinfo)
1963 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1964 struct ad198x_spec *spec = codec->spec;
1965 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1966 spec->num_channel_mode);
1969 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1970 struct snd_ctl_elem_value *ucontrol)
1972 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1973 struct ad198x_spec *spec = codec->spec;
1974 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1975 spec->num_channel_mode, spec->multiout.max_channels);
1978 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1979 struct snd_ctl_elem_value *ucontrol)
1981 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1982 struct ad198x_spec *spec = codec->spec;
1983 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1984 spec->num_channel_mode,
1985 &spec->multiout.max_channels);
1986 if (err >= 0 && spec->need_dac_fix)
1987 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1992 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1993 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1994 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1995 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1996 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1997 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2001 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2002 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2003 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2004 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2005 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2006 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2010 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2011 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2012 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2013 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2014 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2015 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2016 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2017 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2019 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2020 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2021 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2022 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2023 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2024 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2025 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2026 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2028 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2029 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2031 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2032 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2038 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2039 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2040 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2041 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2042 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2046 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2047 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2048 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2049 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2050 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2054 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2055 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2056 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2057 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2058 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2059 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2060 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2062 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2063 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2064 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2065 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2066 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2067 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2068 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2069 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2071 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2072 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2074 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2075 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2077 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2078 .name = "Channel Mode",
2079 .info = ad198x_ch_mode_info,
2080 .get = ad198x_ch_mode_get,
2081 .put = ad198x_ch_mode_put,
2088 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2089 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2090 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2091 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2093 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2094 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2095 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2096 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2097 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2098 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2100 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2101 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2103 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2106 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2107 .name = "External Amplifier",
2108 .info = ad198x_eapd_info,
2109 .get = ad198x_eapd_get,
2110 .put = ad198x_eapd_put,
2111 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2118 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2119 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2120 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2121 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2122 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2123 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2124 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2126 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2127 /* The multiple "Capture Source" controls confuse alsamixer
2128 * So call somewhat different..
2130 /* .name = "Capture Source", */
2131 .name = "Input Source",
2133 .info = ad198x_mux_enum_info,
2134 .get = ad198x_mux_enum_get,
2135 .put = ad198x_mux_enum_put,
2140 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2141 struct snd_ctl_elem_info *uinfo)
2143 static char *texts[] = {
2144 "PCM", "ADC1", "ADC2", "ADC3"
2146 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2148 uinfo->value.enumerated.items = 4;
2149 if (uinfo->value.enumerated.item >= 4)
2150 uinfo->value.enumerated.item = 3;
2151 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2155 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2156 struct snd_ctl_elem_value *ucontrol)
2158 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2161 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2164 ucontrol->value.enumerated.item[0] = 0;
2166 sel = snd_hda_codec_read(codec, 0x0b, 0,
2167 AC_VERB_GET_CONNECT_SEL, 0);
2172 ucontrol->value.enumerated.item[0] = sel;
2177 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2178 struct snd_ctl_elem_value *ucontrol)
2180 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2181 unsigned int val, sel;
2184 val = ucontrol->value.enumerated.item[0];
2188 sel = snd_hda_codec_read(codec, 0x1d, 0,
2189 AC_VERB_GET_AMP_GAIN_MUTE,
2191 change = sel & 0x80;
2193 snd_hda_codec_write_cache(codec, 0x1d, 0,
2194 AC_VERB_SET_AMP_GAIN_MUTE,
2196 snd_hda_codec_write_cache(codec, 0x1d, 0,
2197 AC_VERB_SET_AMP_GAIN_MUTE,
2201 sel = snd_hda_codec_read(codec, 0x1d, 0,
2202 AC_VERB_GET_AMP_GAIN_MUTE,
2203 AC_AMP_GET_INPUT | 0x01);
2204 change = sel & 0x80;
2206 snd_hda_codec_write_cache(codec, 0x1d, 0,
2207 AC_VERB_SET_AMP_GAIN_MUTE,
2209 snd_hda_codec_write_cache(codec, 0x1d, 0,
2210 AC_VERB_SET_AMP_GAIN_MUTE,
2213 sel = snd_hda_codec_read(codec, 0x0b, 0,
2214 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2215 change |= sel != val;
2217 snd_hda_codec_write_cache(codec, 0x0b, 0,
2218 AC_VERB_SET_CONNECT_SEL,
2224 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2225 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2228 .name = "IEC958 Playback Source",
2229 .info = ad1988_spdif_playback_source_info,
2230 .get = ad1988_spdif_playback_source_get,
2231 .put = ad1988_spdif_playback_source_put,
2236 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2237 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2241 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2242 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2243 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2248 * initialization verbs
2252 * for 6-stack (+dig)
2254 static struct hda_verb ad1988_6stack_init_verbs[] = {
2255 /* Front, Surround, CLFE, side DAC; unmute as default */
2256 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2257 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2258 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2259 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2260 /* Port-A front headphon path */
2261 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2262 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2263 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2264 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2265 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2266 /* Port-D line-out path */
2267 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2268 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2269 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2270 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2271 /* Port-F surround path */
2272 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2273 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2274 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2275 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2276 /* Port-G CLFE path */
2277 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2278 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2279 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2280 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2281 /* Port-H side path */
2282 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2283 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2284 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2285 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2287 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2288 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2289 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2290 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2291 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2292 /* Port-B front mic-in path */
2293 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2294 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2295 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2296 /* Port-C line-in path */
2297 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2298 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2299 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2300 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2301 /* Port-E mic-in path */
2302 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2303 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2304 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2305 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2306 /* Analog CD Input */
2307 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2308 /* Analog Mix output amp */
2309 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2314 static struct hda_verb ad1988_capture_init_verbs[] = {
2315 /* mute analog mix */
2316 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2317 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2318 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2319 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2320 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2321 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2322 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2323 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2324 /* select ADCs - front-mic */
2325 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2326 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2327 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2332 static struct hda_verb ad1988_spdif_init_verbs[] = {
2334 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2335 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2336 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2337 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2339 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2344 /* AD1989 has no ADC -> SPDIF route */
2345 static struct hda_verb ad1989_spdif_init_verbs[] = {
2346 /* SPDIF-1 out pin */
2347 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2348 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2349 /* SPDIF-2/HDMI out pin */
2350 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2351 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2356 * verbs for 3stack (+dig)
2358 static struct hda_verb ad1988_3stack_ch2_init[] = {
2359 /* set port-C to line-in */
2360 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2361 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2362 /* set port-E to mic-in */
2363 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2364 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2368 static struct hda_verb ad1988_3stack_ch6_init[] = {
2369 /* set port-C to surround out */
2370 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2371 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2372 /* set port-E to CLFE out */
2373 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2374 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2378 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2379 { 2, ad1988_3stack_ch2_init },
2380 { 6, ad1988_3stack_ch6_init },
2383 static struct hda_verb ad1988_3stack_init_verbs[] = {
2384 /* Front, Surround, CLFE, side DAC; unmute as default */
2385 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2386 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2387 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2388 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2389 /* Port-A front headphon path */
2390 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2391 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2392 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2393 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2394 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2395 /* Port-D line-out path */
2396 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2397 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2398 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2399 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2401 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2402 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2403 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2404 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2405 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2406 /* Port-B front mic-in path */
2407 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2408 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2409 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2410 /* Port-C line-in/surround path - 6ch mode as default */
2411 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2412 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2413 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2414 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2415 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2416 /* Port-E mic-in/CLFE path - 6ch mode as default */
2417 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2418 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2419 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2420 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2421 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2422 /* mute analog mix */
2423 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2424 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2425 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2426 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2427 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2428 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2429 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2430 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2431 /* select ADCs - front-mic */
2432 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2433 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2434 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2435 /* Analog Mix output amp */
2436 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2441 * verbs for laptop mode (+dig)
2443 static struct hda_verb ad1988_laptop_hp_on[] = {
2444 /* unmute port-A and mute port-D */
2445 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2446 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2449 static struct hda_verb ad1988_laptop_hp_off[] = {
2450 /* mute port-A and unmute port-D */
2451 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2452 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2456 #define AD1988_HP_EVENT 0x01
2458 static struct hda_verb ad1988_laptop_init_verbs[] = {
2459 /* Front, Surround, CLFE, side DAC; unmute as default */
2460 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2461 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2462 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2463 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2464 /* Port-A front headphon path */
2465 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2466 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2467 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2468 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2469 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2470 /* unsolicited event for pin-sense */
2471 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2472 /* Port-D line-out path + EAPD */
2473 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2474 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2475 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2476 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2477 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2479 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2480 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2481 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2482 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2483 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2484 /* Port-B mic-in path */
2485 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2486 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2487 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2488 /* Port-C docking station - try to output */
2489 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2490 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2491 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2492 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2493 /* mute analog mix */
2494 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2495 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2496 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2497 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2498 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2499 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2500 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2501 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2502 /* select ADCs - mic */
2503 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2504 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2505 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2506 /* Analog Mix output amp */
2507 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2511 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2513 if ((res >> 26) != AD1988_HP_EVENT)
2515 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2516 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2518 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2521 #ifdef CONFIG_SND_HDA_POWER_SAVE
2522 static struct hda_amp_list ad1988_loopbacks[] = {
2523 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2524 { 0x20, HDA_INPUT, 1 }, /* Line */
2525 { 0x20, HDA_INPUT, 4 }, /* Mic */
2526 { 0x20, HDA_INPUT, 6 }, /* CD */
2532 * Automatic parse of I/O pins from the BIOS configuration
2540 static struct snd_kcontrol_new ad1988_control_templates[] = {
2541 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2542 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2543 HDA_BIND_MUTE(NULL, 0, 0, 0),
2546 /* add dynamic controls */
2547 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2550 struct snd_kcontrol_new *knew;
2552 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2553 knew = snd_array_new(&spec->kctls);
2556 *knew = ad1988_control_templates[type];
2557 knew->name = kstrdup(name, GFP_KERNEL);
2560 knew->private_value = val;
2564 #define AD1988_PIN_CD_NID 0x18
2565 #define AD1988_PIN_BEEP_NID 0x10
2567 static hda_nid_t ad1988_mixer_nids[8] = {
2568 /* A B C D E F G H */
2569 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2572 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2574 static hda_nid_t idx_to_dac[8] = {
2575 /* A B C D E F G H */
2576 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2578 static hda_nid_t idx_to_dac_rev2[8] = {
2579 /* A B C D E F G H */
2580 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2583 return idx_to_dac_rev2[idx];
2585 return idx_to_dac[idx];
2588 static hda_nid_t ad1988_boost_nids[8] = {
2589 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2592 static int ad1988_pin_idx(hda_nid_t nid)
2594 static hda_nid_t ad1988_io_pins[8] = {
2595 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2598 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2599 if (ad1988_io_pins[i] == nid)
2601 return 0; /* should be -1 */
2604 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2606 static int loopback_idx[8] = {
2607 2, 0, 1, 3, 4, 5, 1, 4
2610 case AD1988_PIN_CD_NID:
2613 return loopback_idx[ad1988_pin_idx(nid)];
2617 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2619 static int adc_idx[8] = {
2620 0, 1, 2, 8, 4, 3, 6, 7
2623 case AD1988_PIN_CD_NID:
2626 return adc_idx[ad1988_pin_idx(nid)];
2630 /* fill in the dac_nids table from the parsed pin configuration */
2631 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2632 const struct auto_pin_cfg *cfg)
2634 struct ad198x_spec *spec = codec->spec;
2637 spec->multiout.dac_nids = spec->private_dac_nids;
2639 /* check the pins hardwired to audio widget */
2640 for (i = 0; i < cfg->line_outs; i++) {
2641 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2642 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2644 spec->multiout.num_dacs = cfg->line_outs;
2648 /* add playback controls from the parsed DAC table */
2649 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2650 const struct auto_pin_cfg *cfg)
2653 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2657 for (i = 0; i < cfg->line_outs; i++) {
2658 hda_nid_t dac = spec->multiout.dac_nids[i];
2661 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2664 err = add_control(spec, AD_CTL_WIDGET_VOL,
2665 "Center Playback Volume",
2666 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2669 err = add_control(spec, AD_CTL_WIDGET_VOL,
2670 "LFE Playback Volume",
2671 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2674 err = add_control(spec, AD_CTL_BIND_MUTE,
2675 "Center Playback Switch",
2676 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2679 err = add_control(spec, AD_CTL_BIND_MUTE,
2680 "LFE Playback Switch",
2681 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2685 sprintf(name, "%s Playback Volume", chname[i]);
2686 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2687 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2690 sprintf(name, "%s Playback Switch", chname[i]);
2691 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2692 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2700 /* add playback controls for speaker and HP outputs */
2701 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2704 struct ad198x_spec *spec = codec->spec;
2712 idx = ad1988_pin_idx(pin);
2713 nid = ad1988_idx_to_dac(codec, idx);
2714 /* check whether the corresponding DAC was already taken */
2715 for (i = 0; i < spec->autocfg.line_outs; i++) {
2716 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2717 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2721 if (i >= spec->autocfg.line_outs) {
2722 /* specify the DAC as the extra output */
2723 if (!spec->multiout.hp_nid)
2724 spec->multiout.hp_nid = nid;
2726 spec->multiout.extra_out_nid[0] = nid;
2727 /* control HP volume/switch on the output mixer amp */
2728 sprintf(name, "%s Playback Volume", pfx);
2729 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2730 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2734 nid = ad1988_mixer_nids[idx];
2735 sprintf(name, "%s Playback Switch", pfx);
2736 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2737 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2742 /* create input playback/capture controls for the given pin */
2743 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2744 const char *ctlname, int boost)
2749 sprintf(name, "%s Playback Volume", ctlname);
2750 idx = ad1988_pin_to_loopback_idx(pin);
2751 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2752 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2754 sprintf(name, "%s Playback Switch", ctlname);
2755 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2756 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2760 idx = ad1988_pin_idx(pin);
2761 bnid = ad1988_boost_nids[idx];
2763 sprintf(name, "%s Boost", ctlname);
2764 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2765 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2772 /* create playback/capture controls for input pins */
2773 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2774 const struct auto_pin_cfg *cfg)
2776 struct hda_input_mux *imux = &spec->private_imux;
2779 for (i = 0; i < AUTO_PIN_LAST; i++) {
2780 err = new_analog_input(spec, cfg->input_pins[i],
2781 auto_pin_cfg_labels[i],
2782 i <= AUTO_PIN_FRONT_MIC);
2785 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2786 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2789 imux->items[imux->num_items].label = "Mix";
2790 imux->items[imux->num_items].index = 9;
2793 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2794 "Analog Mix Playback Volume",
2795 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2797 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2798 "Analog Mix Playback Switch",
2799 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2805 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2806 hda_nid_t nid, int pin_type,
2810 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2811 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2813 case 0x11: /* port-A - DAC 04 */
2814 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2816 case 0x14: /* port-B - DAC 06 */
2817 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2819 case 0x15: /* port-C - DAC 05 */
2820 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2822 case 0x17: /* port-E - DAC 0a */
2823 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2825 case 0x13: /* mono - DAC 04 */
2826 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2831 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2833 struct ad198x_spec *spec = codec->spec;
2836 for (i = 0; i < spec->autocfg.line_outs; i++) {
2837 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2838 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2842 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2844 struct ad198x_spec *spec = codec->spec;
2847 pin = spec->autocfg.speaker_pins[0];
2848 if (pin) /* connect to front */
2849 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2850 pin = spec->autocfg.hp_pins[0];
2851 if (pin) /* connect to front */
2852 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2855 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2857 struct ad198x_spec *spec = codec->spec;
2860 for (i = 0; i < AUTO_PIN_LAST; i++) {
2861 hda_nid_t nid = spec->autocfg.input_pins[i];
2865 case 0x15: /* port-C */
2866 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2868 case 0x17: /* port-E */
2869 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2872 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2873 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2874 if (nid != AD1988_PIN_CD_NID)
2875 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2877 idx = ad1988_pin_idx(nid);
2878 if (ad1988_boost_nids[idx])
2879 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2880 AC_VERB_SET_AMP_GAIN_MUTE,
2885 /* parse the BIOS configuration and set up the alc_spec */
2886 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2887 static int ad1988_parse_auto_config(struct hda_codec *codec)
2889 struct ad198x_spec *spec = codec->spec;
2892 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2894 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2896 if (! spec->autocfg.line_outs)
2897 return 0; /* can't find valid BIOS pin config */
2898 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2899 (err = ad1988_auto_create_extra_out(codec,
2900 spec->autocfg.speaker_pins[0],
2902 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2903 "Headphone")) < 0 ||
2904 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2907 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2909 if (spec->autocfg.dig_outs)
2910 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2911 if (spec->autocfg.dig_in_pin)
2912 spec->dig_in_nid = AD1988_SPDIF_IN;
2914 if (spec->kctls.list)
2915 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2917 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2919 spec->input_mux = &spec->private_imux;
2924 /* init callback for auto-configuration model -- overriding the default init */
2925 static int ad1988_auto_init(struct hda_codec *codec)
2928 ad1988_auto_init_multi_out(codec);
2929 ad1988_auto_init_extra_out(codec);
2930 ad1988_auto_init_analog_input(codec);
2938 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2939 [AD1988_6STACK] = "6stack",
2940 [AD1988_6STACK_DIG] = "6stack-dig",
2941 [AD1988_3STACK] = "3stack",
2942 [AD1988_3STACK_DIG] = "3stack-dig",
2943 [AD1988_LAPTOP] = "laptop",
2944 [AD1988_LAPTOP_DIG] = "laptop-dig",
2945 [AD1988_AUTO] = "auto",
2948 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2949 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2950 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2951 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
2952 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
2956 static int patch_ad1988(struct hda_codec *codec)
2958 struct ad198x_spec *spec;
2959 int err, board_config;
2961 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2968 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2970 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2971 ad1988_models, ad1988_cfg_tbl);
2972 if (board_config < 0) {
2973 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2974 board_config = AD1988_AUTO;
2977 if (board_config == AD1988_AUTO) {
2978 /* automatic parse from the BIOS config */
2979 err = ad1988_parse_auto_config(codec);
2984 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2985 board_config = AD1988_6STACK;
2989 err = snd_hda_attach_beep_device(codec, 0x10);
2994 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
2996 switch (board_config) {
2998 case AD1988_6STACK_DIG:
2999 spec->multiout.max_channels = 8;
3000 spec->multiout.num_dacs = 4;
3002 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3004 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3005 spec->input_mux = &ad1988_6stack_capture_source;
3006 spec->num_mixers = 2;
3008 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3010 spec->mixers[0] = ad1988_6stack_mixers1;
3011 spec->mixers[1] = ad1988_6stack_mixers2;
3012 spec->num_init_verbs = 1;
3013 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3014 if (board_config == AD1988_6STACK_DIG) {
3015 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3016 spec->dig_in_nid = AD1988_SPDIF_IN;
3020 case AD1988_3STACK_DIG:
3021 spec->multiout.max_channels = 6;
3022 spec->multiout.num_dacs = 3;
3024 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3026 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3027 spec->input_mux = &ad1988_6stack_capture_source;
3028 spec->channel_mode = ad1988_3stack_modes;
3029 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3030 spec->num_mixers = 2;
3032 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3034 spec->mixers[0] = ad1988_3stack_mixers1;
3035 spec->mixers[1] = ad1988_3stack_mixers2;
3036 spec->num_init_verbs = 1;
3037 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3038 if (board_config == AD1988_3STACK_DIG)
3039 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3042 case AD1988_LAPTOP_DIG:
3043 spec->multiout.max_channels = 2;
3044 spec->multiout.num_dacs = 1;
3045 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3046 spec->input_mux = &ad1988_laptop_capture_source;
3047 spec->num_mixers = 1;
3048 spec->mixers[0] = ad1988_laptop_mixers;
3049 spec->num_init_verbs = 1;
3050 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3051 if (board_config == AD1988_LAPTOP_DIG)
3052 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3056 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3057 spec->adc_nids = ad1988_adc_nids;
3058 spec->capsrc_nids = ad1988_capsrc_nids;
3059 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3060 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3061 if (spec->multiout.dig_out_nid) {
3062 if (codec->vendor_id >= 0x11d4989a) {
3063 spec->mixers[spec->num_mixers++] =
3064 ad1989_spdif_out_mixers;
3065 spec->init_verbs[spec->num_init_verbs++] =
3066 ad1989_spdif_init_verbs;
3067 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3069 spec->mixers[spec->num_mixers++] =
3070 ad1988_spdif_out_mixers;
3071 spec->init_verbs[spec->num_init_verbs++] =
3072 ad1988_spdif_init_verbs;
3075 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3076 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3078 codec->patch_ops = ad198x_patch_ops;
3079 switch (board_config) {
3081 codec->patch_ops.init = ad1988_auto_init;
3084 case AD1988_LAPTOP_DIG:
3085 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3088 #ifdef CONFIG_SND_HDA_POWER_SAVE
3089 spec->loopback.amplist = ad1988_loopbacks;
3091 spec->vmaster_nid = 0x04;
3100 * port-B - front line/mic-in
3101 * port-E - aux in/out
3102 * port-F - aux in/out
3103 * port-C - rear line/mic-in
3104 * port-D - rear line/hp-out
3105 * port-A - front line/hp-out
3107 * AD1984 = AD1884 + two digital mic-ins
3110 * For simplicity, we share the single DAC for both HP and line-outs
3111 * right now. The inidividual playbacks could be easily implemented,
3112 * but no build-up framework is given, so far.
3115 static hda_nid_t ad1884_dac_nids[1] = {
3119 static hda_nid_t ad1884_adc_nids[2] = {
3123 static hda_nid_t ad1884_capsrc_nids[2] = {
3127 #define AD1884_SPDIF_OUT 0x02
3129 static struct hda_input_mux ad1884_capture_source = {
3132 { "Front Mic", 0x0 },
3139 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3140 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3141 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3142 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3143 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3144 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3145 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3146 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3147 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3148 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3149 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3150 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3151 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3152 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3153 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3154 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3155 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3156 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3157 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3159 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3160 /* The multiple "Capture Source" controls confuse alsamixer
3161 * So call somewhat different..
3163 /* .name = "Capture Source", */
3164 .name = "Input Source",
3166 .info = ad198x_mux_enum_info,
3167 .get = ad198x_mux_enum_get,
3168 .put = ad198x_mux_enum_put,
3170 /* SPDIF controls */
3171 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3173 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3174 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3175 /* identical with ad1983 */
3176 .info = ad1983_spdif_route_info,
3177 .get = ad1983_spdif_route_get,
3178 .put = ad1983_spdif_route_put,
3183 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3184 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3185 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3186 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3188 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3194 * initialization verbs
3196 static struct hda_verb ad1884_init_verbs[] = {
3197 /* DACs; mute as default */
3198 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3199 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3200 /* Port-A (HP) mixer */
3201 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3202 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3204 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3205 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3206 /* HP selector - select DAC2 */
3207 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3208 /* Port-D (Line-out) mixer */
3209 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3210 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3212 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3213 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3214 /* Mono-out mixer */
3215 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3216 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3218 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3219 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3221 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3222 /* Port-B (front mic) pin */
3223 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3224 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3225 /* Port-C (rear mic) pin */
3226 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3227 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3228 /* Analog mixer; mute as default */
3229 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3230 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3231 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3232 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3233 /* Analog Mix output amp */
3234 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3235 /* SPDIF output selector */
3236 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3237 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3241 #ifdef CONFIG_SND_HDA_POWER_SAVE
3242 static struct hda_amp_list ad1884_loopbacks[] = {
3243 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3244 { 0x20, HDA_INPUT, 1 }, /* Mic */
3245 { 0x20, HDA_INPUT, 2 }, /* CD */
3246 { 0x20, HDA_INPUT, 4 }, /* Docking */
3251 static const char *ad1884_slave_vols[] = {
3252 "PCM Playback Volume",
3253 "Mic Playback Volume",
3254 "Mono Playback Volume",
3255 "Front Mic Playback Volume",
3256 "Mic Playback Volume",
3257 "CD Playback Volume",
3258 "Internal Mic Playback Volume",
3259 "Docking Mic Playback Volume",
3260 /* "Beep Playback Volume", */
3261 "IEC958 Playback Volume",
3265 static int patch_ad1884(struct hda_codec *codec)
3267 struct ad198x_spec *spec;
3270 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3276 err = snd_hda_attach_beep_device(codec, 0x10);
3281 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3283 spec->multiout.max_channels = 2;
3284 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3285 spec->multiout.dac_nids = ad1884_dac_nids;
3286 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3287 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3288 spec->adc_nids = ad1884_adc_nids;
3289 spec->capsrc_nids = ad1884_capsrc_nids;
3290 spec->input_mux = &ad1884_capture_source;
3291 spec->num_mixers = 1;
3292 spec->mixers[0] = ad1884_base_mixers;
3293 spec->num_init_verbs = 1;
3294 spec->init_verbs[0] = ad1884_init_verbs;
3295 spec->spdif_route = 0;
3296 #ifdef CONFIG_SND_HDA_POWER_SAVE
3297 spec->loopback.amplist = ad1884_loopbacks;
3299 spec->vmaster_nid = 0x04;
3300 /* we need to cover all playback volumes */
3301 spec->slave_vols = ad1884_slave_vols;
3303 codec->patch_ops = ad198x_patch_ops;
3309 * Lenovo Thinkpad T61/X61
3311 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3315 { "Internal Mic", 0x1 },
3317 { "Docking-Station", 0x4 },
3323 * Dell Precision T3400
3325 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3328 { "Front Mic", 0x0 },
3335 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3336 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3337 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3338 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3339 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3340 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3341 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3342 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3343 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3344 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3345 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3346 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3347 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3348 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3349 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3350 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3351 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3352 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3354 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3355 /* The multiple "Capture Source" controls confuse alsamixer
3356 * So call somewhat different..
3358 /* .name = "Capture Source", */
3359 .name = "Input Source",
3361 .info = ad198x_mux_enum_info,
3362 .get = ad198x_mux_enum_get,
3363 .put = ad198x_mux_enum_put,
3365 /* SPDIF controls */
3366 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3368 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3369 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3370 /* identical with ad1983 */
3371 .info = ad1983_spdif_route_info,
3372 .get = ad1983_spdif_route_get,
3373 .put = ad1983_spdif_route_put,
3378 /* additional verbs */
3379 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3380 /* Port-E (docking station mic) pin */
3381 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3382 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3383 /* docking mic boost */
3384 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3385 /* Analog mixer - docking mic; mute as default */
3386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3387 /* enable EAPD bit */
3388 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3393 * Dell Precision T3400
3395 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3396 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3397 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3398 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3399 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3400 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3401 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3402 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3403 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3404 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3405 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3406 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3407 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3408 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3409 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3410 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3412 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3413 /* The multiple "Capture Source" controls confuse alsamixer
3414 * So call somewhat different..
3416 /* .name = "Capture Source", */
3417 .name = "Input Source",
3419 .info = ad198x_mux_enum_info,
3420 .get = ad198x_mux_enum_get,
3421 .put = ad198x_mux_enum_put,
3426 /* Digial MIC ADC NID 0x05 + 0x06 */
3427 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3428 struct hda_codec *codec,
3429 unsigned int stream_tag,
3430 unsigned int format,
3431 struct snd_pcm_substream *substream)
3433 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3434 stream_tag, 0, format);
3438 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3439 struct hda_codec *codec,
3440 struct snd_pcm_substream *substream)
3442 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3446 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3452 .prepare = ad1984_pcm_dmic_prepare,
3453 .cleanup = ad1984_pcm_dmic_cleanup
3457 static int ad1984_build_pcms(struct hda_codec *codec)
3459 struct ad198x_spec *spec = codec->spec;
3460 struct hda_pcm *info;
3463 err = ad198x_build_pcms(codec);
3467 info = spec->pcm_rec + codec->num_pcms;
3469 info->name = "AD1984 Digital Mic";
3470 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3478 AD1984_DELL_DESKTOP,
3482 static const char *ad1984_models[AD1984_MODELS] = {
3483 [AD1984_BASIC] = "basic",
3484 [AD1984_THINKPAD] = "thinkpad",
3485 [AD1984_DELL_DESKTOP] = "dell_desktop",
3488 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3489 /* Lenovo Thinkpad T61/X61 */
3490 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3491 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3495 static int patch_ad1984(struct hda_codec *codec)
3497 struct ad198x_spec *spec;
3498 int board_config, err;
3500 err = patch_ad1884(codec);
3504 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3505 ad1984_models, ad1984_cfg_tbl);
3506 switch (board_config) {
3508 /* additional digital mics */
3509 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3510 codec->patch_ops.build_pcms = ad1984_build_pcms;
3512 case AD1984_THINKPAD:
3513 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3514 spec->input_mux = &ad1984_thinkpad_capture_source;
3515 spec->mixers[0] = ad1984_thinkpad_mixers;
3516 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3518 case AD1984_DELL_DESKTOP:
3519 spec->multiout.dig_out_nid = 0;
3520 spec->input_mux = &ad1984_dell_desktop_capture_source;
3521 spec->mixers[0] = ad1984_dell_desktop_mixers;
3529 * AD1883 / AD1884A / AD1984A / AD1984B
3531 * port-B (0x14) - front mic-in
3532 * port-E (0x1c) - rear mic-in
3533 * port-F (0x16) - CD / ext out
3534 * port-C (0x15) - rear line-in
3535 * port-D (0x12) - rear line-out
3536 * port-A (0x11) - front hp-out
3538 * AD1984A = AD1884A + digital-mic
3539 * AD1883 = equivalent with AD1984A
3540 * AD1984B = AD1984A + extra SPDIF-out
3543 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3546 static hda_nid_t ad1884a_dac_nids[1] = {
3550 #define ad1884a_adc_nids ad1884_adc_nids
3551 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3553 #define AD1884A_SPDIF_OUT 0x02
3555 static struct hda_input_mux ad1884a_capture_source = {
3558 { "Front Mic", 0x0 },
3566 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3567 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3568 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3569 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3570 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3571 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3572 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3573 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3574 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3575 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3576 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3577 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3578 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3579 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3580 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3581 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3582 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3583 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3584 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3585 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3586 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3587 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3588 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3589 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3592 /* The multiple "Capture Source" controls confuse alsamixer
3593 * So call somewhat different..
3595 /* .name = "Capture Source", */
3596 .name = "Input Source",
3598 .info = ad198x_mux_enum_info,
3599 .get = ad198x_mux_enum_get,
3600 .put = ad198x_mux_enum_put,
3602 /* SPDIF controls */
3603 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3605 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3606 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3607 /* identical with ad1983 */
3608 .info = ad1983_spdif_route_info,
3609 .get = ad1983_spdif_route_get,
3610 .put = ad1983_spdif_route_put,
3616 * initialization verbs
3618 static struct hda_verb ad1884a_init_verbs[] = {
3619 /* DACs; unmute as default */
3620 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3621 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3622 /* Port-A (HP) mixer - route only from analog mixer */
3623 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3624 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3626 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3627 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3628 /* Port-D (Line-out) mixer - route only from analog mixer */
3629 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3630 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3632 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3633 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3634 /* Mono-out mixer - route only from analog mixer */
3635 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3636 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3638 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3639 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3640 /* Port-B (front mic) pin */
3641 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3642 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3643 /* Port-C (rear line-in) pin */
3644 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3645 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3646 /* Port-E (rear mic) pin */
3647 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3648 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3649 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3650 /* Port-F (CD) pin */
3651 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3652 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3653 /* Analog mixer; mute as default */
3654 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3655 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3656 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3657 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3658 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3659 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3660 /* Analog Mix output amp */
3661 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3662 /* capture sources */
3663 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3664 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3665 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3666 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3667 /* SPDIF output amp */
3668 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3672 #ifdef CONFIG_SND_HDA_POWER_SAVE
3673 static struct hda_amp_list ad1884a_loopbacks[] = {
3674 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3675 { 0x20, HDA_INPUT, 1 }, /* Mic */
3676 { 0x20, HDA_INPUT, 2 }, /* CD */
3677 { 0x20, HDA_INPUT, 4 }, /* Docking */
3685 * Port A: Headphone jack
3687 * Port C: Internal MIC
3688 * Port D: Dock Line Out (if enabled)
3689 * Port E: Dock Line In (if enabled)
3690 * Port F: Internal speakers
3693 static struct hda_input_mux ad1884a_laptop_capture_source = {
3696 { "Mic", 0x0 }, /* port-B */
3697 { "Internal Mic", 0x1 }, /* port-C */
3698 { "Dock Mic", 0x4 }, /* port-E */
3703 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3704 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3705 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3706 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3707 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3708 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3709 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3710 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3711 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3712 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3713 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3714 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3715 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3716 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3717 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3718 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3719 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3720 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3721 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3724 /* The multiple "Capture Source" controls confuse alsamixer
3725 * So call somewhat different..
3727 /* .name = "Capture Source", */
3728 .name = "Input Source",
3730 .info = ad198x_mux_enum_info,
3731 .get = ad198x_mux_enum_get,
3732 .put = ad198x_mux_enum_put,
3737 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3738 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3739 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3740 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3741 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3742 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3743 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3744 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3745 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3749 /* mute internal speaker if HP is plugged */
3750 static void ad1884a_hp_automute(struct hda_codec *codec)
3752 unsigned int present;
3754 present = snd_hda_codec_read(codec, 0x11, 0,
3755 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3756 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3757 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3758 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3759 present ? 0x00 : 0x02);
3762 /* switch to external mic if plugged */
3763 static void ad1884a_hp_automic(struct hda_codec *codec)
3765 unsigned int present;
3767 present = snd_hda_codec_read(codec, 0x14, 0,
3768 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3769 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3773 #define AD1884A_HP_EVENT 0x37
3774 #define AD1884A_MIC_EVENT 0x36
3776 /* unsolicited event for HP jack sensing */
3777 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3779 switch (res >> 26) {
3780 case AD1884A_HP_EVENT:
3781 ad1884a_hp_automute(codec);
3783 case AD1884A_MIC_EVENT:
3784 ad1884a_hp_automic(codec);
3789 /* initialize jack-sensing, too */
3790 static int ad1884a_hp_init(struct hda_codec *codec)
3793 ad1884a_hp_automute(codec);
3794 ad1884a_hp_automic(codec);
3798 /* additional verbs for laptop model */
3799 static struct hda_verb ad1884a_laptop_verbs[] = {
3800 /* Port-A (HP) pin - always unmuted */
3801 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3802 /* Port-F (int speaker) mixer - route only from analog mixer */
3803 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3804 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3806 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3807 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3808 /* Port-C pin - internal mic-in */
3809 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3810 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3811 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3813 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3814 /* unsolicited event for pin-sense */
3815 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3816 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3820 static struct hda_verb ad1884a_mobile_verbs[] = {
3821 /* DACs; unmute as default */
3822 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3823 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3824 /* Port-A (HP) mixer - route only from analog mixer */
3825 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3826 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3828 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3829 /* Port-A (HP) pin - always unmuted */
3830 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3831 /* Port-B (mic jack) pin */
3832 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3833 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3834 /* Port-C (int mic) pin */
3835 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3836 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3837 /* Port-F (int speaker) mixer - route only from analog mixer */
3838 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3839 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3841 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3842 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3843 /* Analog mixer; mute as default */
3844 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3845 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3846 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3847 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3848 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3849 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3850 /* Analog Mix output amp */
3851 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3852 /* capture sources */
3853 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
3854 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3855 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3856 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3857 /* unsolicited event for pin-sense */
3858 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3859 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3868 * 0x17 - built-in mic
3871 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3873 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3875 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3877 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3878 /* unsolicited event for pin-sense */
3879 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3880 /* internal mic - dmic */
3881 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3882 /* set magic COEFs for dmic */
3883 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3884 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
3888 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3889 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3890 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3891 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3892 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3893 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3894 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3895 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3896 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3897 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3898 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3900 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3901 .name = "Capture Source",
3902 .info = ad198x_mux_enum_info,
3903 .get = ad198x_mux_enum_get,
3904 .put = ad198x_mux_enum_put,
3909 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
3913 { "Internal Mic", 0x5 },
3918 /* mute internal speaker if HP is plugged */
3919 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
3921 unsigned int present;
3923 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
3924 & AC_PINSENSE_PRESENCE;
3925 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
3926 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3929 /* unsolicited event for HP jack sensing */
3930 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
3933 if ((res >> 26) != AD1884A_HP_EVENT)
3935 ad1984a_thinkpad_automute(codec);
3938 /* initialize jack-sensing, too */
3939 static int ad1984a_thinkpad_init(struct hda_codec *codec)
3942 ad1984a_thinkpad_automute(codec);
3957 static const char *ad1884a_models[AD1884A_MODELS] = {
3958 [AD1884A_DESKTOP] = "desktop",
3959 [AD1884A_LAPTOP] = "laptop",
3960 [AD1884A_MOBILE] = "mobile",
3961 [AD1884A_THINKPAD] = "thinkpad",
3964 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3965 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
3966 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
3967 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
3968 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
3969 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
3970 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
3971 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
3975 static int patch_ad1884a(struct hda_codec *codec)
3977 struct ad198x_spec *spec;
3978 int err, board_config;
3980 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3986 err = snd_hda_attach_beep_device(codec, 0x10);
3991 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3993 spec->multiout.max_channels = 2;
3994 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3995 spec->multiout.dac_nids = ad1884a_dac_nids;
3996 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3997 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3998 spec->adc_nids = ad1884a_adc_nids;
3999 spec->capsrc_nids = ad1884a_capsrc_nids;
4000 spec->input_mux = &ad1884a_capture_source;
4001 spec->num_mixers = 1;
4002 spec->mixers[0] = ad1884a_base_mixers;
4003 spec->num_init_verbs = 1;
4004 spec->init_verbs[0] = ad1884a_init_verbs;
4005 spec->spdif_route = 0;
4006 #ifdef CONFIG_SND_HDA_POWER_SAVE
4007 spec->loopback.amplist = ad1884a_loopbacks;
4009 codec->patch_ops = ad198x_patch_ops;
4011 /* override some parameters */
4012 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4015 switch (board_config) {
4016 case AD1884A_LAPTOP:
4017 spec->mixers[0] = ad1884a_laptop_mixers;
4018 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4019 spec->multiout.dig_out_nid = 0;
4020 spec->input_mux = &ad1884a_laptop_capture_source;
4021 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4022 codec->patch_ops.init = ad1884a_hp_init;
4023 /* set the upper-limit for mixer amp to 0dB for avoiding the
4024 * possible damage by overloading
4026 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4027 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4028 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4029 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4030 (1 << AC_AMPCAP_MUTE_SHIFT));
4032 case AD1884A_MOBILE:
4033 spec->mixers[0] = ad1884a_mobile_mixers;
4034 spec->init_verbs[0] = ad1884a_mobile_verbs;
4035 spec->multiout.dig_out_nid = 0;
4036 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4037 codec->patch_ops.init = ad1884a_hp_init;
4038 /* set the upper-limit for mixer amp to 0dB for avoiding the
4039 * possible damage by overloading
4041 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4042 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4043 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4044 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4045 (1 << AC_AMPCAP_MUTE_SHIFT));
4047 case AD1884A_THINKPAD:
4048 spec->mixers[0] = ad1984a_thinkpad_mixers;
4049 spec->init_verbs[spec->num_init_verbs++] =
4050 ad1984a_thinkpad_verbs;
4051 spec->multiout.dig_out_nid = 0;
4052 spec->input_mux = &ad1984a_thinkpad_capture_source;
4053 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4054 codec->patch_ops.init = ad1984a_thinkpad_init;
4065 * port-A - front hp-out
4066 * port-B - front mic-in
4067 * port-C - rear line-in, shared surr-out (3stack)
4068 * port-D - rear line-out
4069 * port-E - rear mic-in, shared clfe-out (3stack)
4070 * port-F - rear surr-out (6stack)
4071 * port-G - rear clfe-out (6stack)
4074 static hda_nid_t ad1882_dac_nids[3] = {
4078 static hda_nid_t ad1882_adc_nids[2] = {
4082 static hda_nid_t ad1882_capsrc_nids[2] = {
4086 #define AD1882_SPDIF_OUT 0x02
4088 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4089 static struct hda_input_mux ad1882_capture_source = {
4092 { "Front Mic", 0x1 },
4100 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4101 static struct hda_input_mux ad1882a_capture_source = {
4104 { "Front Mic", 0x1 },
4107 { "Digital Mic", 0x06 },
4112 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4113 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4114 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4115 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4116 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4117 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4118 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4119 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4120 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4122 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4123 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4124 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4125 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4126 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4127 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4128 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4130 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4131 /* The multiple "Capture Source" controls confuse alsamixer
4132 * So call somewhat different..
4134 /* .name = "Capture Source", */
4135 .name = "Input Source",
4137 .info = ad198x_mux_enum_info,
4138 .get = ad198x_mux_enum_get,
4139 .put = ad198x_mux_enum_put,
4141 /* SPDIF controls */
4142 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4144 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4145 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4146 /* identical with ad1983 */
4147 .info = ad1983_spdif_route_info,
4148 .get = ad1983_spdif_route_get,
4149 .put = ad1983_spdif_route_put,
4154 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4155 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4156 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4157 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4158 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4159 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4160 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4161 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4162 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4166 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4167 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4168 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4169 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4170 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4171 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4172 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4173 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4174 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4175 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4179 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4180 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4181 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4182 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4184 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4185 .name = "Channel Mode",
4186 .info = ad198x_ch_mode_info,
4187 .get = ad198x_ch_mode_get,
4188 .put = ad198x_ch_mode_put,
4193 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4194 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4195 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4196 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4200 static struct hda_verb ad1882_ch2_init[] = {
4201 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4202 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4203 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4204 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4205 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4206 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4210 static struct hda_verb ad1882_ch4_init[] = {
4211 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4212 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4213 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4214 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4215 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4216 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4220 static struct hda_verb ad1882_ch6_init[] = {
4221 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4222 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4223 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4224 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4225 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4226 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4230 static struct hda_channel_mode ad1882_modes[3] = {
4231 { 2, ad1882_ch2_init },
4232 { 4, ad1882_ch4_init },
4233 { 6, ad1882_ch6_init },
4237 * initialization verbs
4239 static struct hda_verb ad1882_init_verbs[] = {
4240 /* DACs; mute as default */
4241 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4242 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4243 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4244 /* Port-A (HP) mixer */
4245 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4246 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4248 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4249 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4250 /* HP selector - select DAC2 */
4251 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4252 /* Port-D (Line-out) mixer */
4253 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4254 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4256 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4257 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4258 /* Mono-out mixer */
4259 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4260 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4262 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4263 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4264 /* Port-B (front mic) pin */
4265 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4266 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4267 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4268 /* Port-C (line-in) pin */
4269 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4270 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4271 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4272 /* Port-C mixer - mute as input */
4273 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4274 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4275 /* Port-E (mic-in) pin */
4276 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4277 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4278 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4279 /* Port-E mixer - mute as input */
4280 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4281 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4282 /* Port-F (surround) */
4283 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4284 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4286 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4287 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4288 /* Analog mixer; mute as default */
4289 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4290 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4291 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4292 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4293 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4294 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4295 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4296 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4297 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4298 /* Analog Mix output amp */
4299 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4300 /* SPDIF output selector */
4301 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4302 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4303 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4307 #ifdef CONFIG_SND_HDA_POWER_SAVE
4308 static struct hda_amp_list ad1882_loopbacks[] = {
4309 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4310 { 0x20, HDA_INPUT, 1 }, /* Mic */
4311 { 0x20, HDA_INPUT, 4 }, /* Line */
4312 { 0x20, HDA_INPUT, 6 }, /* CD */
4324 static const char *ad1882_models[AD1986A_MODELS] = {
4325 [AD1882_3STACK] = "3stack",
4326 [AD1882_6STACK] = "6stack",
4330 static int patch_ad1882(struct hda_codec *codec)
4332 struct ad198x_spec *spec;
4333 int err, board_config;
4335 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4341 err = snd_hda_attach_beep_device(codec, 0x10);
4346 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4348 spec->multiout.max_channels = 6;
4349 spec->multiout.num_dacs = 3;
4350 spec->multiout.dac_nids = ad1882_dac_nids;
4351 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4352 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4353 spec->adc_nids = ad1882_adc_nids;
4354 spec->capsrc_nids = ad1882_capsrc_nids;
4355 if (codec->vendor_id == 0x11d41882)
4356 spec->input_mux = &ad1882_capture_source;
4358 spec->input_mux = &ad1882a_capture_source;
4359 spec->num_mixers = 2;
4360 spec->mixers[0] = ad1882_base_mixers;
4361 if (codec->vendor_id == 0x11d41882)
4362 spec->mixers[1] = ad1882_loopback_mixers;
4364 spec->mixers[1] = ad1882a_loopback_mixers;
4365 spec->num_init_verbs = 1;
4366 spec->init_verbs[0] = ad1882_init_verbs;
4367 spec->spdif_route = 0;
4368 #ifdef CONFIG_SND_HDA_POWER_SAVE
4369 spec->loopback.amplist = ad1882_loopbacks;
4371 spec->vmaster_nid = 0x04;
4373 codec->patch_ops = ad198x_patch_ops;
4375 /* override some parameters */
4376 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4377 ad1882_models, NULL);
4378 switch (board_config) {
4381 spec->num_mixers = 3;
4382 spec->mixers[2] = ad1882_3stack_mixers;
4383 spec->channel_mode = ad1882_modes;
4384 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4385 spec->need_dac_fix = 1;
4386 spec->multiout.max_channels = 2;
4387 spec->multiout.num_dacs = 1;
4390 spec->num_mixers = 3;
4391 spec->mixers[2] = ad1882_6stack_mixers;
4401 static struct hda_codec_preset snd_hda_preset_analog[] = {
4402 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4403 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4404 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4405 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4406 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4407 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4408 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4409 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4410 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4411 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4412 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4413 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4414 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4415 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4416 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4420 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4422 MODULE_LICENSE("GPL");
4423 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4425 static struct hda_codec_preset_list analog_list = {
4426 .preset = snd_hda_preset_analog,
4427 .owner = THIS_MODULE,
4430 static int __init patch_analog_init(void)
4432 return snd_hda_add_codec_preset(&analog_list);
4435 static void __exit patch_analog_exit(void)
4437 snd_hda_delete_codec_preset(&analog_list);
4440 module_init(patch_analog_init)
4441 module_exit(patch_analog_exit)