2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 struct snd_kcontrol_new *mixers[5];
35 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb *init_verbs[5]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs;
42 struct hda_multi_out multiout; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd;
47 unsigned int need_dac_fix;
50 unsigned int num_adc_nids;
52 hda_nid_t dig_in_nid; /* digital-in NID; optional */
55 const struct hda_input_mux *input_mux;
56 hda_nid_t *capsrc_nids;
57 unsigned int cur_mux[3];
60 const struct hda_channel_mode *channel_mode;
64 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
66 unsigned int spdif_route;
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg;
70 struct snd_array kctls;
71 struct hda_input_mux private_imux;
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
74 unsigned int jack_present :1;
75 unsigned int inv_jack_detect:1; /* inverted jack-detection */
76 unsigned int inv_eapd:1; /* inverted EAPD implementation */
78 #ifdef CONFIG_SND_HDA_POWER_SAVE
79 struct hda_loopback_check loopback;
81 /* for virtual master */
82 hda_nid_t vmaster_nid;
83 const char **slave_vols;
84 const char **slave_sws;
88 * input MUX handling (common part)
90 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
92 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
93 struct ad198x_spec *spec = codec->spec;
95 return snd_hda_input_mux_info(spec->input_mux, uinfo);
98 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
100 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
101 struct ad198x_spec *spec = codec->spec;
102 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
104 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
108 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
111 struct ad198x_spec *spec = codec->spec;
112 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
114 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
115 spec->capsrc_nids[adc_idx],
116 &spec->cur_mux[adc_idx]);
120 * initialization (common callbacks)
122 static int ad198x_init(struct hda_codec *codec)
124 struct ad198x_spec *spec = codec->spec;
127 for (i = 0; i < spec->num_init_verbs; i++)
128 snd_hda_sequence_write(codec, spec->init_verbs[i]);
132 static const char *ad_slave_vols[] = {
133 "Front Playback Volume",
134 "Surround Playback Volume",
135 "Center Playback Volume",
136 "LFE Playback Volume",
137 "Side Playback Volume",
138 "Headphone Playback Volume",
139 "Mono Playback Volume",
140 "Speaker Playback Volume",
141 "IEC958 Playback Volume",
145 static const char *ad_slave_sws[] = {
146 "Front Playback Switch",
147 "Surround Playback Switch",
148 "Center Playback Switch",
149 "LFE Playback Switch",
150 "Side Playback Switch",
151 "Headphone Playback Switch",
152 "Mono Playback Switch",
153 "Speaker Playback Switch",
154 "IEC958 Playback Switch",
158 static void ad198x_free_kctls(struct hda_codec *codec);
160 #ifdef CONFIG_SND_HDA_INPUT_BEEP
161 /* additional beep mixers; the actual parameters are overwritten at build */
162 static struct snd_kcontrol_new ad_beep_mixer[] = {
163 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
164 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
168 #define set_beep_amp(spec, nid, idx, dir) \
169 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
171 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
174 static int ad198x_build_controls(struct hda_codec *codec)
176 struct ad198x_spec *spec = codec->spec;
177 struct snd_kcontrol *kctl;
181 for (i = 0; i < spec->num_mixers; i++) {
182 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
186 if (spec->multiout.dig_out_nid) {
187 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
190 err = snd_hda_create_spdif_share_sw(codec,
194 spec->multiout.share_spdif = 1;
196 if (spec->dig_in_nid) {
197 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
202 /* create beep controls if needed */
203 #ifdef CONFIG_SND_HDA_INPUT_BEEP
204 if (spec->beep_amp) {
205 struct snd_kcontrol_new *knew;
206 for (knew = ad_beep_mixer; knew->name; knew++) {
207 struct snd_kcontrol *kctl;
208 kctl = snd_ctl_new1(knew, codec);
211 kctl->private_value = spec->beep_amp;
212 err = snd_hda_ctl_add(codec,
213 get_amp_nid_(spec->beep_amp),
221 /* if we have no master control, let's create it */
222 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
223 unsigned int vmaster_tlv[4];
224 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
225 HDA_OUTPUT, vmaster_tlv);
226 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
229 spec->slave_vols : ad_slave_vols));
233 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
234 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
237 spec->slave_sws : ad_slave_sws));
242 ad198x_free_kctls(codec); /* no longer needed */
244 /* assign Capture Source enums to NID */
245 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
247 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
248 for (i = 0; kctl && i < kctl->count; i++) {
249 err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids,
250 spec->input_mux->num_items);
255 /* assign IEC958 enums to NID */
256 kctl = snd_hda_find_mixer_ctl(codec,
257 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
259 err = snd_hda_add_nid(codec, kctl, 0,
260 spec->multiout.dig_out_nid);
268 #ifdef CONFIG_SND_HDA_POWER_SAVE
269 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
271 struct ad198x_spec *spec = codec->spec;
272 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
277 * Analog playback callbacks
279 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
280 struct hda_codec *codec,
281 struct snd_pcm_substream *substream)
283 struct ad198x_spec *spec = codec->spec;
284 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
288 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
289 struct hda_codec *codec,
290 unsigned int stream_tag,
292 struct snd_pcm_substream *substream)
294 struct ad198x_spec *spec = codec->spec;
295 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
299 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
300 struct hda_codec *codec,
301 struct snd_pcm_substream *substream)
303 struct ad198x_spec *spec = codec->spec;
304 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
310 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
311 struct hda_codec *codec,
312 struct snd_pcm_substream *substream)
314 struct ad198x_spec *spec = codec->spec;
315 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
318 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
319 struct hda_codec *codec,
320 struct snd_pcm_substream *substream)
322 struct ad198x_spec *spec = codec->spec;
323 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
326 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
327 struct hda_codec *codec,
328 unsigned int stream_tag,
330 struct snd_pcm_substream *substream)
332 struct ad198x_spec *spec = codec->spec;
333 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
337 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
338 struct hda_codec *codec,
339 struct snd_pcm_substream *substream)
341 struct ad198x_spec *spec = codec->spec;
342 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
348 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
349 struct hda_codec *codec,
350 unsigned int stream_tag,
352 struct snd_pcm_substream *substream)
354 struct ad198x_spec *spec = codec->spec;
355 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
356 stream_tag, 0, format);
360 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
361 struct hda_codec *codec,
362 struct snd_pcm_substream *substream)
364 struct ad198x_spec *spec = codec->spec;
365 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
372 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
375 .channels_max = 6, /* changed later */
376 .nid = 0, /* fill later */
378 .open = ad198x_playback_pcm_open,
379 .prepare = ad198x_playback_pcm_prepare,
380 .cleanup = ad198x_playback_pcm_cleanup
384 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
388 .nid = 0, /* fill later */
390 .prepare = ad198x_capture_pcm_prepare,
391 .cleanup = ad198x_capture_pcm_cleanup
395 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
399 .nid = 0, /* fill later */
401 .open = ad198x_dig_playback_pcm_open,
402 .close = ad198x_dig_playback_pcm_close,
403 .prepare = ad198x_dig_playback_pcm_prepare,
404 .cleanup = ad198x_dig_playback_pcm_cleanup
408 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
412 /* NID is set in alc_build_pcms */
415 static int ad198x_build_pcms(struct hda_codec *codec)
417 struct ad198x_spec *spec = codec->spec;
418 struct hda_pcm *info = spec->pcm_rec;
421 codec->pcm_info = info;
423 info->name = "AD198x Analog";
424 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
425 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
426 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
427 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
428 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
429 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
431 if (spec->multiout.dig_out_nid) {
434 info->name = "AD198x Digital";
435 info->pcm_type = HDA_PCM_TYPE_SPDIF;
436 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
437 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
438 if (spec->dig_in_nid) {
439 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
440 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
447 static void ad198x_free_kctls(struct hda_codec *codec)
449 struct ad198x_spec *spec = codec->spec;
451 if (spec->kctls.list) {
452 struct snd_kcontrol_new *kctl = spec->kctls.list;
454 for (i = 0; i < spec->kctls.used; i++)
457 snd_array_free(&spec->kctls);
460 static void ad198x_free(struct hda_codec *codec)
462 struct ad198x_spec *spec = codec->spec;
467 ad198x_free_kctls(codec);
469 snd_hda_detach_beep_device(codec);
472 static struct hda_codec_ops ad198x_patch_ops = {
473 .build_controls = ad198x_build_controls,
474 .build_pcms = ad198x_build_pcms,
477 #ifdef CONFIG_SND_HDA_POWER_SAVE
478 .check_power_status = ad198x_check_power_status,
485 * the private value = nid
487 #define ad198x_eapd_info snd_ctl_boolean_mono_info
489 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
490 struct snd_ctl_elem_value *ucontrol)
492 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
493 struct ad198x_spec *spec = codec->spec;
495 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
497 ucontrol->value.integer.value[0] = spec->cur_eapd;
501 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
502 struct snd_ctl_elem_value *ucontrol)
504 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
505 struct ad198x_spec *spec = codec->spec;
506 hda_nid_t nid = kcontrol->private_value & 0xff;
508 eapd = !!ucontrol->value.integer.value[0];
511 if (eapd == spec->cur_eapd)
513 spec->cur_eapd = eapd;
514 snd_hda_codec_write_cache(codec, nid,
515 0, AC_VERB_SET_EAPD_BTLENABLE,
520 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_info *uinfo);
522 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
523 struct snd_ctl_elem_value *ucontrol);
524 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
525 struct snd_ctl_elem_value *ucontrol);
532 #define AD1986A_SPDIF_OUT 0x02
533 #define AD1986A_FRONT_DAC 0x03
534 #define AD1986A_SURR_DAC 0x04
535 #define AD1986A_CLFE_DAC 0x05
536 #define AD1986A_ADC 0x06
538 static hda_nid_t ad1986a_dac_nids[3] = {
539 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
541 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
542 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
544 static struct hda_input_mux ad1986a_capture_source = {
558 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
559 .ops = &snd_hda_bind_vol,
561 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
562 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
563 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
568 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
569 .ops = &snd_hda_bind_sw,
571 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
572 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
573 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
581 static struct snd_kcontrol_new ad1986a_mixers[] = {
583 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
585 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
586 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
587 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
588 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
589 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
590 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
591 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
592 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
593 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
594 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
595 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
596 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
597 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
598 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
599 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
600 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
601 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
602 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
603 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
604 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
605 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
606 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
607 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
608 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
609 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
611 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
612 .name = "Capture Source",
613 .info = ad198x_mux_enum_info,
614 .get = ad198x_mux_enum_get,
615 .put = ad198x_mux_enum_put,
617 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
621 /* additional mixers for 3stack mode */
622 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
624 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
625 .name = "Channel Mode",
626 .info = ad198x_ch_mode_info,
627 .get = ad198x_ch_mode_get,
628 .put = ad198x_ch_mode_put,
633 /* laptop model - 2ch only */
634 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
636 /* master controls both pins 0x1a and 0x1b */
637 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
638 .ops = &snd_hda_bind_vol,
640 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
641 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
646 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
647 .ops = &snd_hda_bind_sw,
649 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
650 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
655 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
656 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
657 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
658 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
659 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
660 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
661 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
662 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
665 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
666 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
667 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
668 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
670 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
671 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
672 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
673 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
675 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
676 .name = "Capture Source",
677 .info = ad198x_mux_enum_info,
678 .get = ad198x_mux_enum_get,
679 .put = ad198x_mux_enum_put,
684 /* laptop-eapd model - 2ch only */
686 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
690 { "Internal Mic", 0x4 },
695 static struct hda_input_mux ad1986a_automic_capture_source = {
703 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
704 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
705 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
709 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
710 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
711 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
712 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
713 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
714 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
715 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
716 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
719 .name = "Capture Source",
720 .info = ad198x_mux_enum_info,
721 .get = ad198x_mux_enum_get,
722 .put = ad198x_mux_enum_put,
725 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
726 .name = "External Amplifier",
727 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
728 .info = ad198x_eapd_info,
729 .get = ad198x_eapd_get,
730 .put = ad198x_eapd_put,
731 .private_value = 0x1b, /* port-D */
736 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
737 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
738 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
742 /* re-connect the mic boost input according to the jack sensing */
743 static void ad1986a_automic(struct hda_codec *codec)
745 unsigned int present;
746 present = snd_hda_jack_detect(codec, 0x1f);
747 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
748 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
752 #define AD1986A_MIC_EVENT 0x36
754 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
757 if ((res >> 26) != AD1986A_MIC_EVENT)
759 ad1986a_automic(codec);
762 static int ad1986a_automic_init(struct hda_codec *codec)
765 ad1986a_automic(codec);
769 /* laptop-automute - 2ch only */
771 static void ad1986a_update_hp(struct hda_codec *codec)
773 struct ad198x_spec *spec = codec->spec;
776 if (spec->jack_present)
777 mute = HDA_AMP_MUTE; /* mute internal speaker */
779 /* unmute internal speaker if necessary */
780 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
781 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
785 static void ad1986a_hp_automute(struct hda_codec *codec)
787 struct ad198x_spec *spec = codec->spec;
789 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
790 if (spec->inv_jack_detect)
791 spec->jack_present = !spec->jack_present;
792 ad1986a_update_hp(codec);
795 #define AD1986A_HP_EVENT 0x37
797 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
799 if ((res >> 26) != AD1986A_HP_EVENT)
801 ad1986a_hp_automute(codec);
804 static int ad1986a_hp_init(struct hda_codec *codec)
807 ad1986a_hp_automute(codec);
811 /* bind hp and internal speaker mute (with plug check) */
812 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
813 struct snd_ctl_elem_value *ucontrol)
815 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
816 long *valp = ucontrol->value.integer.value;
819 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
821 valp[0] ? 0 : HDA_AMP_MUTE);
822 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
824 valp[1] ? 0 : HDA_AMP_MUTE);
826 ad1986a_update_hp(codec);
830 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
831 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
833 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
834 .name = "Master Playback Switch",
835 .subdevice = HDA_SUBDEV_NID_FLAG | HDA_SUBDEV_AMP_FLAG | 0x1a,
836 .info = snd_hda_mixer_amp_switch_info,
837 .get = snd_hda_mixer_amp_switch_get,
838 .put = ad1986a_hp_master_sw_put,
839 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
846 * initialization verbs
848 static struct hda_verb ad1986a_init_verbs[] = {
849 /* Front, Surround, CLFE DAC; mute as default */
850 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
851 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
852 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
854 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
855 /* HP, Line-Out, Surround, CLFE selectors */
856 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
857 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
858 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
859 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
861 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
862 /* Mic selector: Mic 1/2 pin */
863 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
864 /* Line-in selector: Line-in */
865 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
867 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
868 /* Record selector: mic */
869 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
870 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
871 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
872 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
873 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
874 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
875 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
877 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
878 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
879 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
880 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
881 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
882 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
883 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
885 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
886 /* Front, Surround, CLFE Pins */
887 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
888 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
889 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
891 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
893 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
894 /* Line, Aux, CD, Beep-In Pin */
895 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
896 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
897 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
898 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
899 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
903 static struct hda_verb ad1986a_ch2_init[] = {
904 /* Surround out -> Line In */
905 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
906 /* Line-in selectors */
907 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
909 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
910 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
911 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
915 static struct hda_verb ad1986a_ch4_init[] = {
916 /* Surround out -> Surround */
917 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
918 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
920 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
921 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
925 static struct hda_verb ad1986a_ch6_init[] = {
926 /* Surround out -> Surround out */
927 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
928 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
930 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
931 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
935 static struct hda_channel_mode ad1986a_modes[3] = {
936 { 2, ad1986a_ch2_init },
937 { 4, ad1986a_ch4_init },
938 { 6, ad1986a_ch6_init },
941 /* eapd initialization */
942 static struct hda_verb ad1986a_eapd_init_verbs[] = {
943 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
947 static struct hda_verb ad1986a_automic_verbs[] = {
948 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
949 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
950 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
951 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
952 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
956 /* Ultra initialization */
957 static struct hda_verb ad1986a_ultra_init[] = {
958 /* eapd initialization */
959 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
961 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
962 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
963 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
967 /* pin sensing on HP jack */
968 static struct hda_verb ad1986a_hp_init_verbs[] = {
969 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
973 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
977 case AD1986A_HP_EVENT:
978 ad1986a_hp_automute(codec);
980 case AD1986A_MIC_EVENT:
981 ad1986a_automic(codec);
986 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
989 ad1986a_hp_automute(codec);
990 ad1986a_automic(codec);
1000 AD1986A_LAPTOP_EAPD,
1001 AD1986A_LAPTOP_AUTOMUTE,
1004 AD1986A_SAMSUNG_P50,
1008 static const char *ad1986a_models[AD1986A_MODELS] = {
1009 [AD1986A_6STACK] = "6stack",
1010 [AD1986A_3STACK] = "3stack",
1011 [AD1986A_LAPTOP] = "laptop",
1012 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1013 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1014 [AD1986A_ULTRA] = "ultra",
1015 [AD1986A_SAMSUNG] = "samsung",
1016 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1019 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1020 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1021 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1022 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1023 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1024 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1025 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1026 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1027 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1028 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1029 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1030 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1031 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1032 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1033 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1034 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1035 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1036 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
1037 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1038 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1039 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1040 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1041 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1042 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1043 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1044 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1045 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1046 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1050 #ifdef CONFIG_SND_HDA_POWER_SAVE
1051 static struct hda_amp_list ad1986a_loopbacks[] = {
1052 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1053 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1054 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1055 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1056 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1061 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1063 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1064 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1067 static int patch_ad1986a(struct hda_codec *codec)
1069 struct ad198x_spec *spec;
1070 int err, board_config;
1072 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1078 err = snd_hda_attach_beep_device(codec, 0x19);
1083 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1085 spec->multiout.max_channels = 6;
1086 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1087 spec->multiout.dac_nids = ad1986a_dac_nids;
1088 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1089 spec->num_adc_nids = 1;
1090 spec->adc_nids = ad1986a_adc_nids;
1091 spec->capsrc_nids = ad1986a_capsrc_nids;
1092 spec->input_mux = &ad1986a_capture_source;
1093 spec->num_mixers = 1;
1094 spec->mixers[0] = ad1986a_mixers;
1095 spec->num_init_verbs = 1;
1096 spec->init_verbs[0] = ad1986a_init_verbs;
1097 #ifdef CONFIG_SND_HDA_POWER_SAVE
1098 spec->loopback.amplist = ad1986a_loopbacks;
1100 spec->vmaster_nid = 0x1b;
1101 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1103 codec->patch_ops = ad198x_patch_ops;
1105 /* override some parameters */
1106 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1109 switch (board_config) {
1110 case AD1986A_3STACK:
1111 spec->num_mixers = 2;
1112 spec->mixers[1] = ad1986a_3st_mixers;
1113 spec->num_init_verbs = 2;
1114 spec->init_verbs[1] = ad1986a_ch2_init;
1115 spec->channel_mode = ad1986a_modes;
1116 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1117 spec->need_dac_fix = 1;
1118 spec->multiout.max_channels = 2;
1119 spec->multiout.num_dacs = 1;
1121 case AD1986A_LAPTOP:
1122 spec->mixers[0] = ad1986a_laptop_mixers;
1123 spec->multiout.max_channels = 2;
1124 spec->multiout.num_dacs = 1;
1125 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1127 case AD1986A_LAPTOP_EAPD:
1128 spec->num_mixers = 3;
1129 spec->mixers[0] = ad1986a_laptop_master_mixers;
1130 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1131 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1132 spec->num_init_verbs = 2;
1133 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1134 spec->multiout.max_channels = 2;
1135 spec->multiout.num_dacs = 1;
1136 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1137 if (!is_jack_available(codec, 0x25))
1138 spec->multiout.dig_out_nid = 0;
1139 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1141 case AD1986A_SAMSUNG:
1142 spec->num_mixers = 2;
1143 spec->mixers[0] = ad1986a_laptop_master_mixers;
1144 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1145 spec->num_init_verbs = 3;
1146 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1147 spec->init_verbs[2] = ad1986a_automic_verbs;
1148 spec->multiout.max_channels = 2;
1149 spec->multiout.num_dacs = 1;
1150 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1151 if (!is_jack_available(codec, 0x25))
1152 spec->multiout.dig_out_nid = 0;
1153 spec->input_mux = &ad1986a_automic_capture_source;
1154 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1155 codec->patch_ops.init = ad1986a_automic_init;
1157 case AD1986A_SAMSUNG_P50:
1158 spec->num_mixers = 2;
1159 spec->mixers[0] = ad1986a_automute_master_mixers;
1160 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1161 spec->num_init_verbs = 4;
1162 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1163 spec->init_verbs[2] = ad1986a_automic_verbs;
1164 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1165 spec->multiout.max_channels = 2;
1166 spec->multiout.num_dacs = 1;
1167 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1168 if (!is_jack_available(codec, 0x25))
1169 spec->multiout.dig_out_nid = 0;
1170 spec->input_mux = &ad1986a_automic_capture_source;
1171 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1172 codec->patch_ops.init = ad1986a_samsung_p50_init;
1174 case AD1986A_LAPTOP_AUTOMUTE:
1175 spec->num_mixers = 3;
1176 spec->mixers[0] = ad1986a_automute_master_mixers;
1177 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1178 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1179 spec->num_init_verbs = 3;
1180 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1181 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1182 spec->multiout.max_channels = 2;
1183 spec->multiout.num_dacs = 1;
1184 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1185 if (!is_jack_available(codec, 0x25))
1186 spec->multiout.dig_out_nid = 0;
1187 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1188 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1189 codec->patch_ops.init = ad1986a_hp_init;
1190 /* Lenovo N100 seems to report the reversed bit
1191 * for HP jack-sensing
1193 spec->inv_jack_detect = 1;
1196 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1197 spec->num_init_verbs = 2;
1198 spec->init_verbs[1] = ad1986a_ultra_init;
1199 spec->multiout.max_channels = 2;
1200 spec->multiout.num_dacs = 1;
1201 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1202 spec->multiout.dig_out_nid = 0;
1206 /* AD1986A has a hardware problem that it can't share a stream
1207 * with multiple output pins. The copy of front to surrounds
1208 * causes noisy or silent outputs at a certain timing, e.g.
1209 * changing the volume.
1210 * So, let's disable the shared stream.
1212 spec->multiout.no_share_stream = 1;
1221 #define AD1983_SPDIF_OUT 0x02
1222 #define AD1983_DAC 0x03
1223 #define AD1983_ADC 0x04
1225 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1226 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1227 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1229 static struct hda_input_mux ad1983_capture_source = {
1235 { "Mix Mono", 0x3 },
1240 * SPDIF playback route
1242 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1244 static char *texts[] = { "PCM", "ADC" };
1246 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1248 uinfo->value.enumerated.items = 2;
1249 if (uinfo->value.enumerated.item > 1)
1250 uinfo->value.enumerated.item = 1;
1251 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1255 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1258 struct ad198x_spec *spec = codec->spec;
1260 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1264 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1266 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1267 struct ad198x_spec *spec = codec->spec;
1269 if (ucontrol->value.enumerated.item[0] > 1)
1271 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1272 spec->spdif_route = ucontrol->value.enumerated.item[0];
1273 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1274 AC_VERB_SET_CONNECT_SEL,
1281 static struct snd_kcontrol_new ad1983_mixers[] = {
1282 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1283 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1284 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1285 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1286 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1287 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1288 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1289 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1290 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1291 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1292 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1293 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1294 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1295 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1296 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1298 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1299 .name = "Capture Source",
1300 .info = ad198x_mux_enum_info,
1301 .get = ad198x_mux_enum_get,
1302 .put = ad198x_mux_enum_put,
1305 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1306 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1307 .info = ad1983_spdif_route_info,
1308 .get = ad1983_spdif_route_get,
1309 .put = ad1983_spdif_route_put,
1314 static struct hda_verb ad1983_init_verbs[] = {
1315 /* Front, HP, Mono; mute as default */
1316 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1317 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1318 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1319 /* Beep, PCM, Mic, Line-In: mute */
1320 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1321 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1322 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1323 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1324 /* Front, HP selectors; from Mix */
1325 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1326 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1327 /* Mono selector; from Mix */
1328 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1329 /* Mic selector; Mic */
1330 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1331 /* Line-in selector: Line-in */
1332 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1333 /* Mic boost: 0dB */
1334 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1335 /* Record selector: mic */
1336 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1337 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1338 /* SPDIF route: PCM */
1339 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1341 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1343 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1345 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1347 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1349 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1353 #ifdef CONFIG_SND_HDA_POWER_SAVE
1354 static struct hda_amp_list ad1983_loopbacks[] = {
1355 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1356 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1361 static int patch_ad1983(struct hda_codec *codec)
1363 struct ad198x_spec *spec;
1366 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1372 err = snd_hda_attach_beep_device(codec, 0x10);
1377 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1379 spec->multiout.max_channels = 2;
1380 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1381 spec->multiout.dac_nids = ad1983_dac_nids;
1382 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1383 spec->num_adc_nids = 1;
1384 spec->adc_nids = ad1983_adc_nids;
1385 spec->capsrc_nids = ad1983_capsrc_nids;
1386 spec->input_mux = &ad1983_capture_source;
1387 spec->num_mixers = 1;
1388 spec->mixers[0] = ad1983_mixers;
1389 spec->num_init_verbs = 1;
1390 spec->init_verbs[0] = ad1983_init_verbs;
1391 spec->spdif_route = 0;
1392 #ifdef CONFIG_SND_HDA_POWER_SAVE
1393 spec->loopback.amplist = ad1983_loopbacks;
1395 spec->vmaster_nid = 0x05;
1397 codec->patch_ops = ad198x_patch_ops;
1404 * AD1981 HD specific
1407 #define AD1981_SPDIF_OUT 0x02
1408 #define AD1981_DAC 0x03
1409 #define AD1981_ADC 0x04
1411 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1412 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1413 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1415 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1416 static struct hda_input_mux ad1981_capture_source = {
1419 { "Front Mic", 0x0 },
1422 { "Mix Mono", 0x3 },
1429 static struct snd_kcontrol_new ad1981_mixers[] = {
1430 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1431 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1432 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1433 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1434 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1435 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1436 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1437 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1438 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1439 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1440 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1441 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1442 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1443 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1444 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1445 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1446 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1447 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1448 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1449 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1450 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1451 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454 .name = "Capture Source",
1455 .info = ad198x_mux_enum_info,
1456 .get = ad198x_mux_enum_get,
1457 .put = ad198x_mux_enum_put,
1459 /* identical with AD1983 */
1461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1462 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1463 .info = ad1983_spdif_route_info,
1464 .get = ad1983_spdif_route_get,
1465 .put = ad1983_spdif_route_put,
1470 static struct hda_verb ad1981_init_verbs[] = {
1471 /* Front, HP, Mono; mute as default */
1472 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1473 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1474 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1475 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1476 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1477 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1478 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1479 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1480 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1481 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1482 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1483 /* Front, HP selectors; from Mix */
1484 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1485 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1486 /* Mono selector; from Mix */
1487 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1488 /* Mic Mixer; select Front Mic */
1489 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1490 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1491 /* Mic boost: 0dB */
1492 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1493 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1494 /* Record selector: Front mic */
1495 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1496 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1497 /* SPDIF route: PCM */
1498 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1500 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1502 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1504 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1505 /* Front & Rear Mic Pins */
1506 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1507 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1509 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1511 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1512 /* Line-Out as Input: disabled */
1513 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1517 #ifdef CONFIG_SND_HDA_POWER_SAVE
1518 static struct hda_amp_list ad1981_loopbacks[] = {
1519 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1520 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1521 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1522 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1523 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1529 * Patch for HP nx6320
1531 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1532 * speaker output enabled _and_ mute-LED off.
1535 #define AD1981_HP_EVENT 0x37
1536 #define AD1981_MIC_EVENT 0x38
1538 static struct hda_verb ad1981_hp_init_verbs[] = {
1539 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1540 /* pin sensing on HP and Mic jacks */
1541 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1542 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1546 /* turn on/off EAPD (+ mute HP) as a master switch */
1547 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1548 struct snd_ctl_elem_value *ucontrol)
1550 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1551 struct ad198x_spec *spec = codec->spec;
1553 if (! ad198x_eapd_put(kcontrol, ucontrol))
1555 /* change speaker pin appropriately */
1556 snd_hda_codec_write(codec, 0x05, 0,
1557 AC_VERB_SET_PIN_WIDGET_CONTROL,
1558 spec->cur_eapd ? PIN_OUT : 0);
1559 /* toggle HP mute appropriately */
1560 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1562 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1566 /* bind volumes of both NID 0x05 and 0x06 */
1567 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1568 .ops = &snd_hda_bind_vol,
1570 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1571 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1576 /* mute internal speaker if HP is plugged */
1577 static void ad1981_hp_automute(struct hda_codec *codec)
1579 unsigned int present;
1581 present = snd_hda_jack_detect(codec, 0x06);
1582 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1583 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1586 /* toggle input of built-in and mic jack appropriately */
1587 static void ad1981_hp_automic(struct hda_codec *codec)
1589 static struct hda_verb mic_jack_on[] = {
1590 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1591 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1594 static struct hda_verb mic_jack_off[] = {
1595 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1596 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1599 unsigned int present;
1601 present = snd_hda_jack_detect(codec, 0x08);
1603 snd_hda_sequence_write(codec, mic_jack_on);
1605 snd_hda_sequence_write(codec, mic_jack_off);
1608 /* unsolicited event for HP jack sensing */
1609 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1614 case AD1981_HP_EVENT:
1615 ad1981_hp_automute(codec);
1617 case AD1981_MIC_EVENT:
1618 ad1981_hp_automic(codec);
1623 static struct hda_input_mux ad1981_hp_capture_source = {
1627 { "Docking-Station", 0x1 },
1632 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1633 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1635 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1636 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1637 .name = "Master Playback Switch",
1638 .info = ad198x_eapd_info,
1639 .get = ad198x_eapd_get,
1640 .put = ad1981_hp_master_sw_put,
1641 .private_value = 0x05,
1643 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1644 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1646 /* FIXME: analog mic/line loopback doesn't work with my tests...
1647 * (although recording is OK)
1649 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1650 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1651 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1652 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1653 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1654 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1655 /* FIXME: does this laptop have analog CD connection? */
1656 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1657 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1659 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1660 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1661 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1662 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1664 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1665 .name = "Capture Source",
1666 .info = ad198x_mux_enum_info,
1667 .get = ad198x_mux_enum_get,
1668 .put = ad198x_mux_enum_put,
1673 /* initialize jack-sensing, too */
1674 static int ad1981_hp_init(struct hda_codec *codec)
1677 ad1981_hp_automute(codec);
1678 ad1981_hp_automic(codec);
1682 /* configuration for Toshiba Laptops */
1683 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1684 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1685 /* pin sensing on HP and Mic jacks */
1686 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1687 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1691 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1692 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1693 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1697 /* configuration for Lenovo Thinkpad T60 */
1698 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1699 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1700 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1701 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1702 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1703 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1704 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1705 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1706 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1707 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1708 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1709 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1711 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1712 .name = "Capture Source",
1713 .info = ad198x_mux_enum_info,
1714 .get = ad198x_mux_enum_get,
1715 .put = ad198x_mux_enum_put,
1717 /* identical with AD1983 */
1719 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1720 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1721 .info = ad1983_spdif_route_info,
1722 .get = ad1983_spdif_route_get,
1723 .put = ad1983_spdif_route_put,
1728 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1746 static const char *ad1981_models[AD1981_MODELS] = {
1748 [AD1981_THINKPAD] = "thinkpad",
1749 [AD1981_BASIC] = "basic",
1750 [AD1981_TOSHIBA] = "toshiba"
1753 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1754 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1755 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1757 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1758 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1759 /* Lenovo Thinkpad T60/X60/Z6xx */
1760 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1761 /* HP nx6320 (reversed SSID, H/W bug) */
1762 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1766 static int patch_ad1981(struct hda_codec *codec)
1768 struct ad198x_spec *spec;
1769 int err, board_config;
1771 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1777 err = snd_hda_attach_beep_device(codec, 0x10);
1782 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1784 spec->multiout.max_channels = 2;
1785 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1786 spec->multiout.dac_nids = ad1981_dac_nids;
1787 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1788 spec->num_adc_nids = 1;
1789 spec->adc_nids = ad1981_adc_nids;
1790 spec->capsrc_nids = ad1981_capsrc_nids;
1791 spec->input_mux = &ad1981_capture_source;
1792 spec->num_mixers = 1;
1793 spec->mixers[0] = ad1981_mixers;
1794 spec->num_init_verbs = 1;
1795 spec->init_verbs[0] = ad1981_init_verbs;
1796 spec->spdif_route = 0;
1797 #ifdef CONFIG_SND_HDA_POWER_SAVE
1798 spec->loopback.amplist = ad1981_loopbacks;
1800 spec->vmaster_nid = 0x05;
1802 codec->patch_ops = ad198x_patch_ops;
1804 /* override some parameters */
1805 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1808 switch (board_config) {
1810 spec->mixers[0] = ad1981_hp_mixers;
1811 spec->num_init_verbs = 2;
1812 spec->init_verbs[1] = ad1981_hp_init_verbs;
1813 spec->multiout.dig_out_nid = 0;
1814 spec->input_mux = &ad1981_hp_capture_source;
1816 codec->patch_ops.init = ad1981_hp_init;
1817 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1819 case AD1981_THINKPAD:
1820 spec->mixers[0] = ad1981_thinkpad_mixers;
1821 spec->input_mux = &ad1981_thinkpad_capture_source;
1823 case AD1981_TOSHIBA:
1824 spec->mixers[0] = ad1981_hp_mixers;
1825 spec->mixers[1] = ad1981_toshiba_mixers;
1826 spec->num_init_verbs = 2;
1827 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1828 spec->multiout.dig_out_nid = 0;
1829 spec->input_mux = &ad1981_hp_capture_source;
1830 codec->patch_ops.init = ad1981_hp_init;
1831 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1841 * Output pins and routes
1843 * Pin Mix Sel DAC (*)
1844 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1845 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1846 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1847 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1848 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1849 * port-F 0x16 (mute) <- 0x2a <- 06
1850 * port-G 0x24 (mute) <- 0x27 <- 05
1851 * port-H 0x25 (mute) <- 0x28 <- 0a
1852 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1854 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1855 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1857 * Input pins and routes
1859 * pin boost mix input # / adc input #
1860 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1861 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1862 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1863 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1864 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1865 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1866 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1867 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1871 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1872 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1874 * Inputs of Analog Mix (0x20)
1875 * 0:Port-B (front mic)
1876 * 1:Port-C/G/H (line-in)
1878 * 3:Port-D (line-in/2)
1879 * 4:Port-E/G/H (mic-in)
1880 * 5:Port-F (mic2-in)
1886 * 1:Port-B (front mic-in)
1887 * 2:Port-C (line-in)
1888 * 3:Port-F (mic2-in)
1893 * 8:Port-D (line-in/2)
1896 * Proposed pin assignments by the datasheet
1899 * Port-A front headphone
1909 * Port-A front headphone
1911 * C rear line-in/surround
1913 * E rear mic-in/CLFE
1919 * D internal speaker (with EAPD)
1920 * E/F quad mic array
1936 /* reivision id to check workarounds */
1937 #define AD1988A_REV2 0x100200
1939 #define is_rev2(codec) \
1940 ((codec)->vendor_id == 0x11d41988 && \
1941 (codec)->revision_id == AD1988A_REV2)
1947 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1948 0x04, 0x06, 0x05, 0x0a
1951 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1955 /* for AD1988A revision-2, DAC2-4 are swapped */
1956 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1957 0x04, 0x05, 0x0a, 0x06
1960 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1964 static hda_nid_t ad1988_adc_nids[3] = {
1968 static hda_nid_t ad1988_capsrc_nids[3] = {
1972 #define AD1988_SPDIF_OUT 0x02
1973 #define AD1988_SPDIF_OUT_HDMI 0x0b
1974 #define AD1988_SPDIF_IN 0x07
1976 static hda_nid_t ad1989b_slave_dig_outs[] = {
1977 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
1980 static struct hda_input_mux ad1988_6stack_capture_source = {
1983 { "Front Mic", 0x1 }, /* port-B */
1984 { "Line", 0x2 }, /* port-C */
1985 { "Mic", 0x4 }, /* port-E */
1991 static struct hda_input_mux ad1988_laptop_capture_source = {
1994 { "Mic/Line", 0x1 }, /* port-B */
2002 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2003 struct snd_ctl_elem_info *uinfo)
2005 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2006 struct ad198x_spec *spec = codec->spec;
2007 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2008 spec->num_channel_mode);
2011 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2012 struct snd_ctl_elem_value *ucontrol)
2014 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2015 struct ad198x_spec *spec = codec->spec;
2016 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2017 spec->num_channel_mode, spec->multiout.max_channels);
2020 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2021 struct snd_ctl_elem_value *ucontrol)
2023 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2024 struct ad198x_spec *spec = codec->spec;
2025 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2026 spec->num_channel_mode,
2027 &spec->multiout.max_channels);
2028 if (err >= 0 && spec->need_dac_fix)
2029 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2034 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2035 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2036 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2037 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2038 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2039 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2043 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2044 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2045 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2046 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2047 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2048 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2052 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2053 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2054 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2055 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2056 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2057 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2058 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2059 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2061 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2062 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2063 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2064 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2065 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2066 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2067 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2068 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2070 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2071 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2073 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2074 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2080 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2081 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2082 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2083 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2084 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2088 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2089 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2090 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2091 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2092 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2096 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2097 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2098 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2099 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2100 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2101 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2102 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2104 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2105 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2106 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2107 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2108 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2109 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2110 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2111 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2113 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2114 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2116 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2117 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2119 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2120 .name = "Channel Mode",
2121 .info = ad198x_ch_mode_info,
2122 .get = ad198x_ch_mode_get,
2123 .put = ad198x_ch_mode_put,
2130 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2131 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2132 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2133 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2135 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2136 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2137 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2138 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2139 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2140 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2142 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2143 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2145 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2148 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2149 .name = "External Amplifier",
2150 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2151 .info = ad198x_eapd_info,
2152 .get = ad198x_eapd_get,
2153 .put = ad198x_eapd_put,
2154 .private_value = 0x12, /* port-D */
2161 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2162 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2163 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2164 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2165 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2166 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2167 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2169 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2170 /* The multiple "Capture Source" controls confuse alsamixer
2171 * So call somewhat different..
2173 /* .name = "Capture Source", */
2174 .name = "Input Source",
2176 .info = ad198x_mux_enum_info,
2177 .get = ad198x_mux_enum_get,
2178 .put = ad198x_mux_enum_put,
2183 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2184 struct snd_ctl_elem_info *uinfo)
2186 static char *texts[] = {
2187 "PCM", "ADC1", "ADC2", "ADC3"
2189 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2191 uinfo->value.enumerated.items = 4;
2192 if (uinfo->value.enumerated.item >= 4)
2193 uinfo->value.enumerated.item = 3;
2194 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2198 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2199 struct snd_ctl_elem_value *ucontrol)
2201 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2204 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2207 ucontrol->value.enumerated.item[0] = 0;
2209 sel = snd_hda_codec_read(codec, 0x0b, 0,
2210 AC_VERB_GET_CONNECT_SEL, 0);
2215 ucontrol->value.enumerated.item[0] = sel;
2220 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2221 struct snd_ctl_elem_value *ucontrol)
2223 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2224 unsigned int val, sel;
2227 val = ucontrol->value.enumerated.item[0];
2231 sel = snd_hda_codec_read(codec, 0x1d, 0,
2232 AC_VERB_GET_AMP_GAIN_MUTE,
2234 change = sel & 0x80;
2236 snd_hda_codec_write_cache(codec, 0x1d, 0,
2237 AC_VERB_SET_AMP_GAIN_MUTE,
2239 snd_hda_codec_write_cache(codec, 0x1d, 0,
2240 AC_VERB_SET_AMP_GAIN_MUTE,
2244 sel = snd_hda_codec_read(codec, 0x1d, 0,
2245 AC_VERB_GET_AMP_GAIN_MUTE,
2246 AC_AMP_GET_INPUT | 0x01);
2247 change = sel & 0x80;
2249 snd_hda_codec_write_cache(codec, 0x1d, 0,
2250 AC_VERB_SET_AMP_GAIN_MUTE,
2252 snd_hda_codec_write_cache(codec, 0x1d, 0,
2253 AC_VERB_SET_AMP_GAIN_MUTE,
2256 sel = snd_hda_codec_read(codec, 0x0b, 0,
2257 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2258 change |= sel != val;
2260 snd_hda_codec_write_cache(codec, 0x0b, 0,
2261 AC_VERB_SET_CONNECT_SEL,
2267 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2268 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2270 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2271 .name = "IEC958 Playback Source",
2272 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2273 .info = ad1988_spdif_playback_source_info,
2274 .get = ad1988_spdif_playback_source_get,
2275 .put = ad1988_spdif_playback_source_put,
2280 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2281 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2285 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2286 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2287 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2292 * initialization verbs
2296 * for 6-stack (+dig)
2298 static struct hda_verb ad1988_6stack_init_verbs[] = {
2299 /* Front, Surround, CLFE, side DAC; unmute as default */
2300 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2301 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2302 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2303 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2304 /* Port-A front headphon path */
2305 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2306 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2307 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2308 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2309 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2310 /* Port-D line-out path */
2311 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2312 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2313 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2314 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2315 /* Port-F surround path */
2316 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2317 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2318 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2319 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2320 /* Port-G CLFE path */
2321 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2322 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2323 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2324 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2325 /* Port-H side path */
2326 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2327 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2328 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2329 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2331 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2332 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2333 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2334 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2335 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2336 /* Port-B front mic-in path */
2337 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2338 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2339 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2340 /* Port-C line-in path */
2341 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2342 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2343 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2344 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2345 /* Port-E mic-in path */
2346 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2347 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2348 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2349 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2350 /* Analog CD Input */
2351 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2352 /* Analog Mix output amp */
2353 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2358 static struct hda_verb ad1988_capture_init_verbs[] = {
2359 /* mute analog mix */
2360 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2361 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2362 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2363 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2364 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2365 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2366 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2367 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2368 /* select ADCs - front-mic */
2369 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2370 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2371 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2376 static struct hda_verb ad1988_spdif_init_verbs[] = {
2378 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2379 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2380 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2381 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2383 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2388 /* AD1989 has no ADC -> SPDIF route */
2389 static struct hda_verb ad1989_spdif_init_verbs[] = {
2390 /* SPDIF-1 out pin */
2391 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2392 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2393 /* SPDIF-2/HDMI out pin */
2394 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2395 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2400 * verbs for 3stack (+dig)
2402 static struct hda_verb ad1988_3stack_ch2_init[] = {
2403 /* set port-C to line-in */
2404 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2405 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2406 /* set port-E to mic-in */
2407 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2408 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2412 static struct hda_verb ad1988_3stack_ch6_init[] = {
2413 /* set port-C to surround out */
2414 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2415 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2416 /* set port-E to CLFE out */
2417 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2418 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2422 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2423 { 2, ad1988_3stack_ch2_init },
2424 { 6, ad1988_3stack_ch6_init },
2427 static struct hda_verb ad1988_3stack_init_verbs[] = {
2428 /* Front, Surround, CLFE, side DAC; unmute as default */
2429 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2430 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2431 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2432 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2433 /* Port-A front headphon path */
2434 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2435 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2436 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2437 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2438 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2439 /* Port-D line-out path */
2440 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2441 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2442 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2443 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2445 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2446 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2447 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2448 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2449 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2450 /* Port-B front mic-in path */
2451 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2452 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2453 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2454 /* Port-C line-in/surround path - 6ch mode as default */
2455 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2456 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2457 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2458 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2459 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2460 /* Port-E mic-in/CLFE path - 6ch mode as default */
2461 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2462 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2463 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2464 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2465 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2466 /* mute analog mix */
2467 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2468 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2469 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2470 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2471 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2472 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2473 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2474 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2475 /* select ADCs - front-mic */
2476 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2477 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2478 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2479 /* Analog Mix output amp */
2480 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2485 * verbs for laptop mode (+dig)
2487 static struct hda_verb ad1988_laptop_hp_on[] = {
2488 /* unmute port-A and mute port-D */
2489 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2490 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2493 static struct hda_verb ad1988_laptop_hp_off[] = {
2494 /* mute port-A and unmute port-D */
2495 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2496 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2500 #define AD1988_HP_EVENT 0x01
2502 static struct hda_verb ad1988_laptop_init_verbs[] = {
2503 /* Front, Surround, CLFE, side DAC; unmute as default */
2504 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2505 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2506 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2507 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2508 /* Port-A front headphon path */
2509 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2510 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2511 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2512 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2513 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2514 /* unsolicited event for pin-sense */
2515 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2516 /* Port-D line-out path + EAPD */
2517 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2518 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2519 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2520 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2521 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2523 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2524 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2525 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2526 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2527 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2528 /* Port-B mic-in path */
2529 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2530 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2531 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2532 /* Port-C docking station - try to output */
2533 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2534 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2535 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2536 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2537 /* mute analog mix */
2538 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2539 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2540 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2541 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2542 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2543 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2546 /* select ADCs - mic */
2547 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2548 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2549 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2550 /* Analog Mix output amp */
2551 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2555 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2557 if ((res >> 26) != AD1988_HP_EVENT)
2559 if (snd_hda_jack_detect(codec, 0x11))
2560 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2562 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2565 #ifdef CONFIG_SND_HDA_POWER_SAVE
2566 static struct hda_amp_list ad1988_loopbacks[] = {
2567 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2568 { 0x20, HDA_INPUT, 1 }, /* Line */
2569 { 0x20, HDA_INPUT, 4 }, /* Mic */
2570 { 0x20, HDA_INPUT, 6 }, /* CD */
2576 * Automatic parse of I/O pins from the BIOS configuration
2584 static struct snd_kcontrol_new ad1988_control_templates[] = {
2585 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2586 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2587 HDA_BIND_MUTE(NULL, 0, 0, 0),
2590 /* add dynamic controls */
2591 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2594 struct snd_kcontrol_new *knew;
2596 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2597 knew = snd_array_new(&spec->kctls);
2600 *knew = ad1988_control_templates[type];
2601 knew->name = kstrdup(name, GFP_KERNEL);
2604 if (get_amp_nid_(val))
2605 knew->subdevice = HDA_SUBDEV_NID_FLAG |
2606 HDA_SUBDEV_AMP_FLAG |
2608 knew->private_value = val;
2612 #define AD1988_PIN_CD_NID 0x18
2613 #define AD1988_PIN_BEEP_NID 0x10
2615 static hda_nid_t ad1988_mixer_nids[8] = {
2616 /* A B C D E F G H */
2617 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2620 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2622 static hda_nid_t idx_to_dac[8] = {
2623 /* A B C D E F G H */
2624 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2626 static hda_nid_t idx_to_dac_rev2[8] = {
2627 /* A B C D E F G H */
2628 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2631 return idx_to_dac_rev2[idx];
2633 return idx_to_dac[idx];
2636 static hda_nid_t ad1988_boost_nids[8] = {
2637 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2640 static int ad1988_pin_idx(hda_nid_t nid)
2642 static hda_nid_t ad1988_io_pins[8] = {
2643 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2646 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2647 if (ad1988_io_pins[i] == nid)
2649 return 0; /* should be -1 */
2652 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2654 static int loopback_idx[8] = {
2655 2, 0, 1, 3, 4, 5, 1, 4
2658 case AD1988_PIN_CD_NID:
2661 return loopback_idx[ad1988_pin_idx(nid)];
2665 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2667 static int adc_idx[8] = {
2668 0, 1, 2, 8, 4, 3, 6, 7
2671 case AD1988_PIN_CD_NID:
2674 return adc_idx[ad1988_pin_idx(nid)];
2678 /* fill in the dac_nids table from the parsed pin configuration */
2679 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2680 const struct auto_pin_cfg *cfg)
2682 struct ad198x_spec *spec = codec->spec;
2685 spec->multiout.dac_nids = spec->private_dac_nids;
2687 /* check the pins hardwired to audio widget */
2688 for (i = 0; i < cfg->line_outs; i++) {
2689 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2690 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2692 spec->multiout.num_dacs = cfg->line_outs;
2696 /* add playback controls from the parsed DAC table */
2697 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2698 const struct auto_pin_cfg *cfg)
2701 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2705 for (i = 0; i < cfg->line_outs; i++) {
2706 hda_nid_t dac = spec->multiout.dac_nids[i];
2709 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2712 err = add_control(spec, AD_CTL_WIDGET_VOL,
2713 "Center Playback Volume",
2714 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2717 err = add_control(spec, AD_CTL_WIDGET_VOL,
2718 "LFE Playback Volume",
2719 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2722 err = add_control(spec, AD_CTL_BIND_MUTE,
2723 "Center Playback Switch",
2724 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2727 err = add_control(spec, AD_CTL_BIND_MUTE,
2728 "LFE Playback Switch",
2729 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2733 sprintf(name, "%s Playback Volume", chname[i]);
2734 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2735 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2738 sprintf(name, "%s Playback Switch", chname[i]);
2739 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2740 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2748 /* add playback controls for speaker and HP outputs */
2749 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2752 struct ad198x_spec *spec = codec->spec;
2760 idx = ad1988_pin_idx(pin);
2761 nid = ad1988_idx_to_dac(codec, idx);
2762 /* check whether the corresponding DAC was already taken */
2763 for (i = 0; i < spec->autocfg.line_outs; i++) {
2764 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2765 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2769 if (i >= spec->autocfg.line_outs) {
2770 /* specify the DAC as the extra output */
2771 if (!spec->multiout.hp_nid)
2772 spec->multiout.hp_nid = nid;
2774 spec->multiout.extra_out_nid[0] = nid;
2775 /* control HP volume/switch on the output mixer amp */
2776 sprintf(name, "%s Playback Volume", pfx);
2777 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2778 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2782 nid = ad1988_mixer_nids[idx];
2783 sprintf(name, "%s Playback Switch", pfx);
2784 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2785 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2790 /* create input playback/capture controls for the given pin */
2791 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2792 const char *ctlname, int boost)
2797 sprintf(name, "%s Playback Volume", ctlname);
2798 idx = ad1988_pin_to_loopback_idx(pin);
2799 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2800 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2802 sprintf(name, "%s Playback Switch", ctlname);
2803 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2804 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2808 idx = ad1988_pin_idx(pin);
2809 bnid = ad1988_boost_nids[idx];
2811 sprintf(name, "%s Boost", ctlname);
2812 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2813 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2820 /* create playback/capture controls for input pins */
2821 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2822 const struct auto_pin_cfg *cfg)
2824 struct hda_input_mux *imux = &spec->private_imux;
2827 for (i = 0; i < AUTO_PIN_LAST; i++) {
2828 err = new_analog_input(spec, cfg->input_pins[i],
2829 auto_pin_cfg_labels[i],
2830 i <= AUTO_PIN_FRONT_MIC);
2833 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2834 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2837 imux->items[imux->num_items].label = "Mix";
2838 imux->items[imux->num_items].index = 9;
2841 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2842 "Analog Mix Playback Volume",
2843 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2845 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2846 "Analog Mix Playback Switch",
2847 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2853 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2854 hda_nid_t nid, int pin_type,
2858 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2859 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2861 case 0x11: /* port-A - DAC 04 */
2862 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2864 case 0x14: /* port-B - DAC 06 */
2865 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2867 case 0x15: /* port-C - DAC 05 */
2868 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2870 case 0x17: /* port-E - DAC 0a */
2871 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2873 case 0x13: /* mono - DAC 04 */
2874 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2879 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2881 struct ad198x_spec *spec = codec->spec;
2884 for (i = 0; i < spec->autocfg.line_outs; i++) {
2885 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2886 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2890 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2892 struct ad198x_spec *spec = codec->spec;
2895 pin = spec->autocfg.speaker_pins[0];
2896 if (pin) /* connect to front */
2897 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2898 pin = spec->autocfg.hp_pins[0];
2899 if (pin) /* connect to front */
2900 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2903 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2905 struct ad198x_spec *spec = codec->spec;
2908 for (i = 0; i < AUTO_PIN_LAST; i++) {
2909 hda_nid_t nid = spec->autocfg.input_pins[i];
2913 case 0x15: /* port-C */
2914 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2916 case 0x17: /* port-E */
2917 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2920 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2921 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2922 if (nid != AD1988_PIN_CD_NID)
2923 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2925 idx = ad1988_pin_idx(nid);
2926 if (ad1988_boost_nids[idx])
2927 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2928 AC_VERB_SET_AMP_GAIN_MUTE,
2933 /* parse the BIOS configuration and set up the alc_spec */
2934 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2935 static int ad1988_parse_auto_config(struct hda_codec *codec)
2937 struct ad198x_spec *spec = codec->spec;
2940 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2942 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2944 if (! spec->autocfg.line_outs)
2945 return 0; /* can't find valid BIOS pin config */
2946 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2947 (err = ad1988_auto_create_extra_out(codec,
2948 spec->autocfg.speaker_pins[0],
2950 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2951 "Headphone")) < 0 ||
2952 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2955 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2957 if (spec->autocfg.dig_outs)
2958 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2959 if (spec->autocfg.dig_in_pin)
2960 spec->dig_in_nid = AD1988_SPDIF_IN;
2962 if (spec->kctls.list)
2963 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2965 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2967 spec->input_mux = &spec->private_imux;
2972 /* init callback for auto-configuration model -- overriding the default init */
2973 static int ad1988_auto_init(struct hda_codec *codec)
2976 ad1988_auto_init_multi_out(codec);
2977 ad1988_auto_init_extra_out(codec);
2978 ad1988_auto_init_analog_input(codec);
2986 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2987 [AD1988_6STACK] = "6stack",
2988 [AD1988_6STACK_DIG] = "6stack-dig",
2989 [AD1988_3STACK] = "3stack",
2990 [AD1988_3STACK_DIG] = "3stack-dig",
2991 [AD1988_LAPTOP] = "laptop",
2992 [AD1988_LAPTOP_DIG] = "laptop-dig",
2993 [AD1988_AUTO] = "auto",
2996 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2997 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2998 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2999 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3000 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3004 static int patch_ad1988(struct hda_codec *codec)
3006 struct ad198x_spec *spec;
3007 int err, board_config;
3009 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3016 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3018 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3019 ad1988_models, ad1988_cfg_tbl);
3020 if (board_config < 0) {
3021 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3023 board_config = AD1988_AUTO;
3026 if (board_config == AD1988_AUTO) {
3027 /* automatic parse from the BIOS config */
3028 err = ad1988_parse_auto_config(codec);
3033 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3034 board_config = AD1988_6STACK;
3038 err = snd_hda_attach_beep_device(codec, 0x10);
3043 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3045 switch (board_config) {
3047 case AD1988_6STACK_DIG:
3048 spec->multiout.max_channels = 8;
3049 spec->multiout.num_dacs = 4;
3051 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3053 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3054 spec->input_mux = &ad1988_6stack_capture_source;
3055 spec->num_mixers = 2;
3057 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3059 spec->mixers[0] = ad1988_6stack_mixers1;
3060 spec->mixers[1] = ad1988_6stack_mixers2;
3061 spec->num_init_verbs = 1;
3062 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3063 if (board_config == AD1988_6STACK_DIG) {
3064 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3065 spec->dig_in_nid = AD1988_SPDIF_IN;
3069 case AD1988_3STACK_DIG:
3070 spec->multiout.max_channels = 6;
3071 spec->multiout.num_dacs = 3;
3073 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3075 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3076 spec->input_mux = &ad1988_6stack_capture_source;
3077 spec->channel_mode = ad1988_3stack_modes;
3078 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3079 spec->num_mixers = 2;
3081 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3083 spec->mixers[0] = ad1988_3stack_mixers1;
3084 spec->mixers[1] = ad1988_3stack_mixers2;
3085 spec->num_init_verbs = 1;
3086 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3087 if (board_config == AD1988_3STACK_DIG)
3088 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3091 case AD1988_LAPTOP_DIG:
3092 spec->multiout.max_channels = 2;
3093 spec->multiout.num_dacs = 1;
3094 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3095 spec->input_mux = &ad1988_laptop_capture_source;
3096 spec->num_mixers = 1;
3097 spec->mixers[0] = ad1988_laptop_mixers;
3098 spec->inv_eapd = 1; /* inverted EAPD */
3099 spec->num_init_verbs = 1;
3100 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3101 if (board_config == AD1988_LAPTOP_DIG)
3102 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3106 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3107 spec->adc_nids = ad1988_adc_nids;
3108 spec->capsrc_nids = ad1988_capsrc_nids;
3109 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3110 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3111 if (spec->multiout.dig_out_nid) {
3112 if (codec->vendor_id >= 0x11d4989a) {
3113 spec->mixers[spec->num_mixers++] =
3114 ad1989_spdif_out_mixers;
3115 spec->init_verbs[spec->num_init_verbs++] =
3116 ad1989_spdif_init_verbs;
3117 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3119 spec->mixers[spec->num_mixers++] =
3120 ad1988_spdif_out_mixers;
3121 spec->init_verbs[spec->num_init_verbs++] =
3122 ad1988_spdif_init_verbs;
3125 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3126 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3128 codec->patch_ops = ad198x_patch_ops;
3129 switch (board_config) {
3131 codec->patch_ops.init = ad1988_auto_init;
3134 case AD1988_LAPTOP_DIG:
3135 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3138 #ifdef CONFIG_SND_HDA_POWER_SAVE
3139 spec->loopback.amplist = ad1988_loopbacks;
3141 spec->vmaster_nid = 0x04;
3150 * port-B - front line/mic-in
3151 * port-E - aux in/out
3152 * port-F - aux in/out
3153 * port-C - rear line/mic-in
3154 * port-D - rear line/hp-out
3155 * port-A - front line/hp-out
3157 * AD1984 = AD1884 + two digital mic-ins
3160 * For simplicity, we share the single DAC for both HP and line-outs
3161 * right now. The inidividual playbacks could be easily implemented,
3162 * but no build-up framework is given, so far.
3165 static hda_nid_t ad1884_dac_nids[1] = {
3169 static hda_nid_t ad1884_adc_nids[2] = {
3173 static hda_nid_t ad1884_capsrc_nids[2] = {
3177 #define AD1884_SPDIF_OUT 0x02
3179 static struct hda_input_mux ad1884_capture_source = {
3182 { "Front Mic", 0x0 },
3189 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3190 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3191 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3192 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3193 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3194 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3195 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3196 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3197 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3198 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3199 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3200 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3201 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3202 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3203 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3204 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3205 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3206 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3207 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3210 /* The multiple "Capture Source" controls confuse alsamixer
3211 * So call somewhat different..
3213 /* .name = "Capture Source", */
3214 .name = "Input Source",
3216 .info = ad198x_mux_enum_info,
3217 .get = ad198x_mux_enum_get,
3218 .put = ad198x_mux_enum_put,
3220 /* SPDIF controls */
3221 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3223 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3224 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3225 /* identical with ad1983 */
3226 .info = ad1983_spdif_route_info,
3227 .get = ad1983_spdif_route_get,
3228 .put = ad1983_spdif_route_put,
3233 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3234 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3235 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3236 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3238 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3244 * initialization verbs
3246 static struct hda_verb ad1884_init_verbs[] = {
3247 /* DACs; mute as default */
3248 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3249 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3250 /* Port-A (HP) mixer */
3251 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3252 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3254 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3255 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3256 /* HP selector - select DAC2 */
3257 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3258 /* Port-D (Line-out) mixer */
3259 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3260 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3262 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3263 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3264 /* Mono-out mixer */
3265 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3266 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3268 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3269 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3271 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3272 /* Port-B (front mic) pin */
3273 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3274 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3275 /* Port-C (rear mic) pin */
3276 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3277 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3278 /* Analog mixer; mute as default */
3279 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3280 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3281 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3282 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3283 /* Analog Mix output amp */
3284 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3285 /* SPDIF output selector */
3286 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3287 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3291 #ifdef CONFIG_SND_HDA_POWER_SAVE
3292 static struct hda_amp_list ad1884_loopbacks[] = {
3293 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3294 { 0x20, HDA_INPUT, 1 }, /* Mic */
3295 { 0x20, HDA_INPUT, 2 }, /* CD */
3296 { 0x20, HDA_INPUT, 4 }, /* Docking */
3301 static const char *ad1884_slave_vols[] = {
3302 "PCM Playback Volume",
3303 "Mic Playback Volume",
3304 "Mono Playback Volume",
3305 "Front Mic Playback Volume",
3306 "Mic Playback Volume",
3307 "CD Playback Volume",
3308 "Internal Mic Playback Volume",
3309 "Docking Mic Playback Volume",
3310 /* "Beep Playback Volume", */
3311 "IEC958 Playback Volume",
3315 static int patch_ad1884(struct hda_codec *codec)
3317 struct ad198x_spec *spec;
3320 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3326 err = snd_hda_attach_beep_device(codec, 0x10);
3331 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3333 spec->multiout.max_channels = 2;
3334 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3335 spec->multiout.dac_nids = ad1884_dac_nids;
3336 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3337 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3338 spec->adc_nids = ad1884_adc_nids;
3339 spec->capsrc_nids = ad1884_capsrc_nids;
3340 spec->input_mux = &ad1884_capture_source;
3341 spec->num_mixers = 1;
3342 spec->mixers[0] = ad1884_base_mixers;
3343 spec->num_init_verbs = 1;
3344 spec->init_verbs[0] = ad1884_init_verbs;
3345 spec->spdif_route = 0;
3346 #ifdef CONFIG_SND_HDA_POWER_SAVE
3347 spec->loopback.amplist = ad1884_loopbacks;
3349 spec->vmaster_nid = 0x04;
3350 /* we need to cover all playback volumes */
3351 spec->slave_vols = ad1884_slave_vols;
3353 codec->patch_ops = ad198x_patch_ops;
3359 * Lenovo Thinkpad T61/X61
3361 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3365 { "Internal Mic", 0x1 },
3367 { "Docking-Station", 0x4 },
3373 * Dell Precision T3400
3375 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3378 { "Front Mic", 0x0 },
3385 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3386 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3387 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3388 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3389 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3390 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3391 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3392 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3393 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3394 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3395 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3396 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3397 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3398 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3399 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3400 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3401 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3402 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3404 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3405 /* The multiple "Capture Source" controls confuse alsamixer
3406 * So call somewhat different..
3408 /* .name = "Capture Source", */
3409 .name = "Input Source",
3411 .info = ad198x_mux_enum_info,
3412 .get = ad198x_mux_enum_get,
3413 .put = ad198x_mux_enum_put,
3415 /* SPDIF controls */
3416 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3419 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3420 /* identical with ad1983 */
3421 .info = ad1983_spdif_route_info,
3422 .get = ad1983_spdif_route_get,
3423 .put = ad1983_spdif_route_put,
3428 /* additional verbs */
3429 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3430 /* Port-E (docking station mic) pin */
3431 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3432 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3433 /* docking mic boost */
3434 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3435 /* Analog mixer - docking mic; mute as default */
3436 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3437 /* enable EAPD bit */
3438 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3443 * Dell Precision T3400
3445 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3446 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3447 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3448 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3449 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3450 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3451 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3452 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3453 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3454 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3455 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3456 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3457 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3458 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3459 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3460 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3462 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3463 /* The multiple "Capture Source" controls confuse alsamixer
3464 * So call somewhat different..
3466 /* .name = "Capture Source", */
3467 .name = "Input Source",
3469 .info = ad198x_mux_enum_info,
3470 .get = ad198x_mux_enum_get,
3471 .put = ad198x_mux_enum_put,
3476 /* Digial MIC ADC NID 0x05 + 0x06 */
3477 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3478 struct hda_codec *codec,
3479 unsigned int stream_tag,
3480 unsigned int format,
3481 struct snd_pcm_substream *substream)
3483 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3484 stream_tag, 0, format);
3488 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3489 struct hda_codec *codec,
3490 struct snd_pcm_substream *substream)
3492 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3496 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3502 .prepare = ad1984_pcm_dmic_prepare,
3503 .cleanup = ad1984_pcm_dmic_cleanup
3507 static int ad1984_build_pcms(struct hda_codec *codec)
3509 struct ad198x_spec *spec = codec->spec;
3510 struct hda_pcm *info;
3513 err = ad198x_build_pcms(codec);
3517 info = spec->pcm_rec + codec->num_pcms;
3519 info->name = "AD1984 Digital Mic";
3520 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3528 AD1984_DELL_DESKTOP,
3532 static const char *ad1984_models[AD1984_MODELS] = {
3533 [AD1984_BASIC] = "basic",
3534 [AD1984_THINKPAD] = "thinkpad",
3535 [AD1984_DELL_DESKTOP] = "dell_desktop",
3538 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3539 /* Lenovo Thinkpad T61/X61 */
3540 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3541 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3545 static int patch_ad1984(struct hda_codec *codec)
3547 struct ad198x_spec *spec;
3548 int board_config, err;
3550 err = patch_ad1884(codec);
3554 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3555 ad1984_models, ad1984_cfg_tbl);
3556 switch (board_config) {
3558 /* additional digital mics */
3559 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3560 codec->patch_ops.build_pcms = ad1984_build_pcms;
3562 case AD1984_THINKPAD:
3563 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3564 spec->input_mux = &ad1984_thinkpad_capture_source;
3565 spec->mixers[0] = ad1984_thinkpad_mixers;
3566 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3568 case AD1984_DELL_DESKTOP:
3569 spec->multiout.dig_out_nid = 0;
3570 spec->input_mux = &ad1984_dell_desktop_capture_source;
3571 spec->mixers[0] = ad1984_dell_desktop_mixers;
3579 * AD1883 / AD1884A / AD1984A / AD1984B
3581 * port-B (0x14) - front mic-in
3582 * port-E (0x1c) - rear mic-in
3583 * port-F (0x16) - CD / ext out
3584 * port-C (0x15) - rear line-in
3585 * port-D (0x12) - rear line-out
3586 * port-A (0x11) - front hp-out
3588 * AD1984A = AD1884A + digital-mic
3589 * AD1883 = equivalent with AD1984A
3590 * AD1984B = AD1984A + extra SPDIF-out
3593 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3596 static hda_nid_t ad1884a_dac_nids[1] = {
3600 #define ad1884a_adc_nids ad1884_adc_nids
3601 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3603 #define AD1884A_SPDIF_OUT 0x02
3605 static struct hda_input_mux ad1884a_capture_source = {
3608 { "Front Mic", 0x0 },
3616 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3617 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3618 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3619 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3620 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3621 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3622 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3623 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3624 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3625 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3626 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3627 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3628 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3629 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3630 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3631 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3632 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3633 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3634 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3635 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3636 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3637 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3638 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3639 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3642 /* The multiple "Capture Source" controls confuse alsamixer
3643 * So call somewhat different..
3645 /* .name = "Capture Source", */
3646 .name = "Input Source",
3648 .info = ad198x_mux_enum_info,
3649 .get = ad198x_mux_enum_get,
3650 .put = ad198x_mux_enum_put,
3652 /* SPDIF controls */
3653 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3655 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3656 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3657 /* identical with ad1983 */
3658 .info = ad1983_spdif_route_info,
3659 .get = ad1983_spdif_route_get,
3660 .put = ad1983_spdif_route_put,
3666 * initialization verbs
3668 static struct hda_verb ad1884a_init_verbs[] = {
3669 /* DACs; unmute as default */
3670 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3671 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3672 /* Port-A (HP) mixer - route only from analog mixer */
3673 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3674 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3676 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3677 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3678 /* Port-D (Line-out) mixer - route only from analog mixer */
3679 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3680 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3682 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3683 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3684 /* Mono-out mixer - route only from analog mixer */
3685 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3686 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3688 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3689 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3690 /* Port-B (front mic) pin */
3691 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3692 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3693 /* Port-C (rear line-in) pin */
3694 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3695 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3696 /* Port-E (rear mic) pin */
3697 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3698 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3699 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3700 /* Port-F (CD) pin */
3701 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3702 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3703 /* Analog mixer; mute as default */
3704 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3705 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3706 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3707 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3708 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3709 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3710 /* Analog Mix output amp */
3711 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3712 /* capture sources */
3713 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3714 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3715 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3716 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3717 /* SPDIF output amp */
3718 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3722 #ifdef CONFIG_SND_HDA_POWER_SAVE
3723 static struct hda_amp_list ad1884a_loopbacks[] = {
3724 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3725 { 0x20, HDA_INPUT, 1 }, /* Mic */
3726 { 0x20, HDA_INPUT, 2 }, /* CD */
3727 { 0x20, HDA_INPUT, 4 }, /* Docking */
3735 * Port A: Headphone jack
3737 * Port C: Internal MIC
3738 * Port D: Dock Line Out (if enabled)
3739 * Port E: Dock Line In (if enabled)
3740 * Port F: Internal speakers
3743 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3744 struct snd_ctl_elem_value *ucontrol)
3746 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3747 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3748 int mute = (!ucontrol->value.integer.value[0] &&
3749 !ucontrol->value.integer.value[1]);
3750 /* toggle GPIO1 according to the mute state */
3751 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3756 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3757 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3759 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3760 .name = "Master Playback Switch",
3761 .subdevice = HDA_SUBDEV_NID_FLAG | HDA_SUBDEV_AMP_FLAG | 0x21,
3762 .info = snd_hda_mixer_amp_switch_info,
3763 .get = snd_hda_mixer_amp_switch_get,
3764 .put = ad1884a_mobile_master_sw_put,
3765 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3767 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3768 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3769 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3770 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3771 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3772 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3773 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3774 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3775 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3776 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3777 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3778 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3779 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3780 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3784 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3785 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3786 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3789 .name = "Master Playback Switch",
3790 .subdevice = HDA_SUBDEV_NID_FLAG | HDA_SUBDEV_AMP_FLAG | 0x21,
3791 .info = snd_hda_mixer_amp_switch_info,
3792 .get = snd_hda_mixer_amp_switch_get,
3793 .put = ad1884a_mobile_master_sw_put,
3794 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3796 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3797 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3798 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3799 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3800 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3801 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3805 /* mute internal speaker if HP is plugged */
3806 static void ad1884a_hp_automute(struct hda_codec *codec)
3808 unsigned int present;
3810 present = snd_hda_jack_detect(codec, 0x11);
3811 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3812 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3813 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3814 present ? 0x00 : 0x02);
3817 /* switch to external mic if plugged */
3818 static void ad1884a_hp_automic(struct hda_codec *codec)
3820 unsigned int present;
3822 present = snd_hda_jack_detect(codec, 0x14);
3823 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3827 #define AD1884A_HP_EVENT 0x37
3828 #define AD1884A_MIC_EVENT 0x36
3830 /* unsolicited event for HP jack sensing */
3831 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3833 switch (res >> 26) {
3834 case AD1884A_HP_EVENT:
3835 ad1884a_hp_automute(codec);
3837 case AD1884A_MIC_EVENT:
3838 ad1884a_hp_automic(codec);
3843 /* initialize jack-sensing, too */
3844 static int ad1884a_hp_init(struct hda_codec *codec)
3847 ad1884a_hp_automute(codec);
3848 ad1884a_hp_automic(codec);
3852 /* mute internal speaker if HP or docking HP is plugged */
3853 static void ad1884a_laptop_automute(struct hda_codec *codec)
3855 unsigned int present;
3857 present = snd_hda_jack_detect(codec, 0x11);
3859 present = snd_hda_jack_detect(codec, 0x12);
3860 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3861 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3862 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3863 present ? 0x00 : 0x02);
3866 /* switch to external mic if plugged */
3867 static void ad1884a_laptop_automic(struct hda_codec *codec)
3871 if (snd_hda_jack_detect(codec, 0x14))
3873 else if (snd_hda_jack_detect(codec, 0x1c))
3877 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3880 /* unsolicited event for HP jack sensing */
3881 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3884 switch (res >> 26) {
3885 case AD1884A_HP_EVENT:
3886 ad1884a_laptop_automute(codec);
3888 case AD1884A_MIC_EVENT:
3889 ad1884a_laptop_automic(codec);
3894 /* initialize jack-sensing, too */
3895 static int ad1884a_laptop_init(struct hda_codec *codec)
3898 ad1884a_laptop_automute(codec);
3899 ad1884a_laptop_automic(codec);
3903 /* additional verbs for laptop model */
3904 static struct hda_verb ad1884a_laptop_verbs[] = {
3905 /* Port-A (HP) pin - always unmuted */
3906 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3907 /* Port-F (int speaker) mixer - route only from analog mixer */
3908 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3909 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3910 /* Port-F (int speaker) pin */
3911 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3912 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3913 /* required for compaq 6530s/6531s speaker output */
3914 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3915 /* Port-C pin - internal mic-in */
3916 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3917 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3918 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3919 /* Port-D (docking line-out) pin - default unmuted */
3920 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3922 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3923 /* unsolicited event for pin-sense */
3924 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3925 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3926 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3927 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3928 /* allow to touch GPIO1 (for mute control) */
3929 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3930 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3931 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3935 static struct hda_verb ad1884a_mobile_verbs[] = {
3936 /* DACs; unmute as default */
3937 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3938 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3939 /* Port-A (HP) mixer - route only from analog mixer */
3940 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3941 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3943 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3944 /* Port-A (HP) pin - always unmuted */
3945 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3946 /* Port-B (mic jack) pin */
3947 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3948 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3949 /* Port-C (int mic) pin */
3950 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3951 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3952 /* Port-F (int speaker) mixer - route only from analog mixer */
3953 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3954 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3956 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3957 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3958 /* Analog mixer; mute as default */
3959 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3960 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3961 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3962 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3963 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3964 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3965 /* Analog Mix output amp */
3966 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3967 /* capture sources */
3968 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
3969 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3970 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3971 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3972 /* unsolicited event for pin-sense */
3973 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3974 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3975 /* allow to touch GPIO1 (for mute control) */
3976 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3977 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3978 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3987 * 0x17 - built-in mic
3990 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3992 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3994 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3996 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3997 /* unsolicited event for pin-sense */
3998 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3999 /* internal mic - dmic */
4000 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4001 /* set magic COEFs for dmic */
4002 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4003 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4007 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4008 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4009 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4010 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4011 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4012 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4013 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4014 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4015 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4016 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4017 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4019 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4020 .name = "Capture Source",
4021 .info = ad198x_mux_enum_info,
4022 .get = ad198x_mux_enum_get,
4023 .put = ad198x_mux_enum_put,
4028 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4032 { "Internal Mic", 0x5 },
4037 /* mute internal speaker if HP is plugged */
4038 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4040 unsigned int present;
4042 present = snd_hda_jack_detect(codec, 0x11);
4043 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4044 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4047 /* unsolicited event for HP jack sensing */
4048 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4051 if ((res >> 26) != AD1884A_HP_EVENT)
4053 ad1984a_thinkpad_automute(codec);
4056 /* initialize jack-sensing, too */
4057 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4060 ad1984a_thinkpad_automute(codec);
4066 * port-A (0x11) - front hp-out
4067 * port-B (0x14) - unused
4068 * port-C (0x15) - unused
4069 * port-D (0x12) - rear line out
4070 * port-E (0x1c) - front mic-in
4071 * port-F (0x16) - Internal speakers
4072 * digital-mic (0x17) - Internal mic
4075 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4076 /* DACs; unmute as default */
4077 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4078 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4079 /* Port-A (HP) mixer - route only from analog mixer */
4080 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4081 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4083 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4084 /* Port-A (HP) pin - always unmuted */
4085 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4086 /* Port-E (int speaker) mixer - route only from analog mixer */
4087 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4089 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4090 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4091 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4092 /* Port-F (int speaker) mixer - route only from analog mixer */
4093 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4094 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4096 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4097 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4098 /* Analog mixer; mute as default */
4099 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4100 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4101 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4102 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4103 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4104 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4105 /* Analog Mix output amp */
4106 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4107 /* capture sources */
4108 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4109 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4110 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4111 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4112 /* unsolicited event for pin-sense */
4113 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4114 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4115 /* allow to touch GPIO1 (for mute control) */
4116 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4117 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4118 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4119 /* internal mic - dmic */
4120 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4121 /* set magic COEFs for dmic */
4122 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4123 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4127 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4128 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4129 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4131 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4132 .subdevice = HDA_SUBDEV_NID_FLAG | HDA_SUBDEV_AMP_FLAG | 0x21,
4133 .name = "Master Playback Switch",
4134 .info = snd_hda_mixer_amp_switch_info,
4135 .get = snd_hda_mixer_amp_switch_get,
4136 .put = ad1884a_mobile_master_sw_put,
4137 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4139 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4140 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4141 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4142 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4143 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4144 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4148 /* switch to external mic if plugged */
4149 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4151 if (snd_hda_jack_detect(codec, 0x1c))
4152 snd_hda_codec_write(codec, 0x0c, 0,
4153 AC_VERB_SET_CONNECT_SEL, 0x4);
4155 snd_hda_codec_write(codec, 0x0c, 0,
4156 AC_VERB_SET_CONNECT_SEL, 0x5);
4160 /* unsolicited event for HP jack sensing */
4161 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4164 switch (res >> 26) {
4165 case AD1884A_HP_EVENT:
4166 ad1884a_hp_automute(codec);
4168 case AD1884A_MIC_EVENT:
4169 ad1984a_touchsmart_automic(codec);
4174 /* initialize jack-sensing, too */
4175 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4178 ad1884a_hp_automute(codec);
4179 ad1984a_touchsmart_automic(codec);
4196 static const char *ad1884a_models[AD1884A_MODELS] = {
4197 [AD1884A_DESKTOP] = "desktop",
4198 [AD1884A_LAPTOP] = "laptop",
4199 [AD1884A_MOBILE] = "mobile",
4200 [AD1884A_THINKPAD] = "thinkpad",
4201 [AD1984A_TOUCHSMART] = "touchsmart",
4204 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4205 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4206 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4207 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4208 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4209 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4210 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4211 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4212 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4213 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4214 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4218 static int patch_ad1884a(struct hda_codec *codec)
4220 struct ad198x_spec *spec;
4221 int err, board_config;
4223 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4229 err = snd_hda_attach_beep_device(codec, 0x10);
4234 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4236 spec->multiout.max_channels = 2;
4237 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4238 spec->multiout.dac_nids = ad1884a_dac_nids;
4239 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4240 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4241 spec->adc_nids = ad1884a_adc_nids;
4242 spec->capsrc_nids = ad1884a_capsrc_nids;
4243 spec->input_mux = &ad1884a_capture_source;
4244 spec->num_mixers = 1;
4245 spec->mixers[0] = ad1884a_base_mixers;
4246 spec->num_init_verbs = 1;
4247 spec->init_verbs[0] = ad1884a_init_verbs;
4248 spec->spdif_route = 0;
4249 #ifdef CONFIG_SND_HDA_POWER_SAVE
4250 spec->loopback.amplist = ad1884a_loopbacks;
4252 codec->patch_ops = ad198x_patch_ops;
4254 /* override some parameters */
4255 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4258 switch (board_config) {
4259 case AD1884A_LAPTOP:
4260 spec->mixers[0] = ad1884a_laptop_mixers;
4261 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4262 spec->multiout.dig_out_nid = 0;
4263 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4264 codec->patch_ops.init = ad1884a_laptop_init;
4265 /* set the upper-limit for mixer amp to 0dB for avoiding the
4266 * possible damage by overloading
4268 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4269 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4270 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4271 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4272 (1 << AC_AMPCAP_MUTE_SHIFT));
4274 case AD1884A_MOBILE:
4275 spec->mixers[0] = ad1884a_mobile_mixers;
4276 spec->init_verbs[0] = ad1884a_mobile_verbs;
4277 spec->multiout.dig_out_nid = 0;
4278 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4279 codec->patch_ops.init = ad1884a_hp_init;
4280 /* set the upper-limit for mixer amp to 0dB for avoiding the
4281 * possible damage by overloading
4283 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4284 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4285 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4286 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4287 (1 << AC_AMPCAP_MUTE_SHIFT));
4289 case AD1884A_THINKPAD:
4290 spec->mixers[0] = ad1984a_thinkpad_mixers;
4291 spec->init_verbs[spec->num_init_verbs++] =
4292 ad1984a_thinkpad_verbs;
4293 spec->multiout.dig_out_nid = 0;
4294 spec->input_mux = &ad1984a_thinkpad_capture_source;
4295 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4296 codec->patch_ops.init = ad1984a_thinkpad_init;
4298 case AD1984A_TOUCHSMART:
4299 spec->mixers[0] = ad1984a_touchsmart_mixers;
4300 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4301 spec->multiout.dig_out_nid = 0;
4302 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4303 codec->patch_ops.init = ad1984a_touchsmart_init;
4304 /* set the upper-limit for mixer amp to 0dB for avoiding the
4305 * possible damage by overloading
4307 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4308 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4309 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4310 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4311 (1 << AC_AMPCAP_MUTE_SHIFT));
4322 * port-A - front hp-out
4323 * port-B - front mic-in
4324 * port-C - rear line-in, shared surr-out (3stack)
4325 * port-D - rear line-out
4326 * port-E - rear mic-in, shared clfe-out (3stack)
4327 * port-F - rear surr-out (6stack)
4328 * port-G - rear clfe-out (6stack)
4331 static hda_nid_t ad1882_dac_nids[3] = {
4335 static hda_nid_t ad1882_adc_nids[2] = {
4339 static hda_nid_t ad1882_capsrc_nids[2] = {
4343 #define AD1882_SPDIF_OUT 0x02
4345 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4346 static struct hda_input_mux ad1882_capture_source = {
4349 { "Front Mic", 0x1 },
4357 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4358 static struct hda_input_mux ad1882a_capture_source = {
4361 { "Front Mic", 0x1 },
4364 { "Digital Mic", 0x06 },
4369 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4370 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4371 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4372 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4373 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4374 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4375 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4376 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4377 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4379 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4380 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4381 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4382 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4383 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4384 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4385 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4387 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4388 /* The multiple "Capture Source" controls confuse alsamixer
4389 * So call somewhat different..
4391 /* .name = "Capture Source", */
4392 .name = "Input Source",
4394 .info = ad198x_mux_enum_info,
4395 .get = ad198x_mux_enum_get,
4396 .put = ad198x_mux_enum_put,
4398 /* SPDIF controls */
4399 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4402 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4403 /* identical with ad1983 */
4404 .info = ad1983_spdif_route_info,
4405 .get = ad1983_spdif_route_get,
4406 .put = ad1983_spdif_route_put,
4411 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4412 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4413 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4414 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4415 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4416 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4417 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4418 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4419 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4423 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4424 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4425 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4426 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4427 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4428 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4429 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4430 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4431 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4432 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4436 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4437 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4438 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4439 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4442 .name = "Channel Mode",
4443 .info = ad198x_ch_mode_info,
4444 .get = ad198x_ch_mode_get,
4445 .put = ad198x_ch_mode_put,
4450 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4451 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4452 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4453 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4457 static struct hda_verb ad1882_ch2_init[] = {
4458 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4459 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4460 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4461 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4462 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4463 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4467 static struct hda_verb ad1882_ch4_init[] = {
4468 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4469 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4470 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4471 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4472 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4473 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4477 static struct hda_verb ad1882_ch6_init[] = {
4478 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4479 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4480 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4481 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4482 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4483 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4487 static struct hda_channel_mode ad1882_modes[3] = {
4488 { 2, ad1882_ch2_init },
4489 { 4, ad1882_ch4_init },
4490 { 6, ad1882_ch6_init },
4494 * initialization verbs
4496 static struct hda_verb ad1882_init_verbs[] = {
4497 /* DACs; mute as default */
4498 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4499 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4500 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4501 /* Port-A (HP) mixer */
4502 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4503 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4505 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4506 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4507 /* HP selector - select DAC2 */
4508 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4509 /* Port-D (Line-out) mixer */
4510 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4511 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4513 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4514 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4515 /* Mono-out mixer */
4516 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4517 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4519 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4520 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4521 /* Port-B (front mic) pin */
4522 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4523 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4524 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4525 /* Port-C (line-in) pin */
4526 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4527 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4528 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4529 /* Port-C mixer - mute as input */
4530 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4531 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4532 /* Port-E (mic-in) pin */
4533 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4534 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4535 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4536 /* Port-E mixer - mute as input */
4537 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4538 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4539 /* Port-F (surround) */
4540 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4541 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4543 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4544 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4545 /* Analog mixer; mute as default */
4546 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4549 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4550 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4551 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4552 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4553 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4554 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4555 /* Analog Mix output amp */
4556 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4557 /* SPDIF output selector */
4558 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4559 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4560 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4564 #ifdef CONFIG_SND_HDA_POWER_SAVE
4565 static struct hda_amp_list ad1882_loopbacks[] = {
4566 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4567 { 0x20, HDA_INPUT, 1 }, /* Mic */
4568 { 0x20, HDA_INPUT, 4 }, /* Line */
4569 { 0x20, HDA_INPUT, 6 }, /* CD */
4581 static const char *ad1882_models[AD1986A_MODELS] = {
4582 [AD1882_3STACK] = "3stack",
4583 [AD1882_6STACK] = "6stack",
4587 static int patch_ad1882(struct hda_codec *codec)
4589 struct ad198x_spec *spec;
4590 int err, board_config;
4592 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4598 err = snd_hda_attach_beep_device(codec, 0x10);
4603 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4605 spec->multiout.max_channels = 6;
4606 spec->multiout.num_dacs = 3;
4607 spec->multiout.dac_nids = ad1882_dac_nids;
4608 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4609 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4610 spec->adc_nids = ad1882_adc_nids;
4611 spec->capsrc_nids = ad1882_capsrc_nids;
4612 if (codec->vendor_id == 0x11d41882)
4613 spec->input_mux = &ad1882_capture_source;
4615 spec->input_mux = &ad1882a_capture_source;
4616 spec->num_mixers = 2;
4617 spec->mixers[0] = ad1882_base_mixers;
4618 if (codec->vendor_id == 0x11d41882)
4619 spec->mixers[1] = ad1882_loopback_mixers;
4621 spec->mixers[1] = ad1882a_loopback_mixers;
4622 spec->num_init_verbs = 1;
4623 spec->init_verbs[0] = ad1882_init_verbs;
4624 spec->spdif_route = 0;
4625 #ifdef CONFIG_SND_HDA_POWER_SAVE
4626 spec->loopback.amplist = ad1882_loopbacks;
4628 spec->vmaster_nid = 0x04;
4630 codec->patch_ops = ad198x_patch_ops;
4632 /* override some parameters */
4633 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4634 ad1882_models, NULL);
4635 switch (board_config) {
4638 spec->num_mixers = 3;
4639 spec->mixers[2] = ad1882_3stack_mixers;
4640 spec->channel_mode = ad1882_modes;
4641 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4642 spec->need_dac_fix = 1;
4643 spec->multiout.max_channels = 2;
4644 spec->multiout.num_dacs = 1;
4647 spec->num_mixers = 3;
4648 spec->mixers[2] = ad1882_6stack_mixers;
4658 static struct hda_codec_preset snd_hda_preset_analog[] = {
4659 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4660 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4661 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4662 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4663 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4664 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4665 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4666 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4667 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4668 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4669 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4670 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4671 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4672 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4673 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4677 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4679 MODULE_LICENSE("GPL");
4680 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4682 static struct hda_codec_preset_list analog_list = {
4683 .preset = snd_hda_preset_analog,
4684 .owner = THIS_MODULE,
4687 static int __init patch_analog_init(void)
4689 return snd_hda_add_codec_preset(&analog_list);
4692 static void __exit patch_analog_exit(void)
4694 snd_hda_delete_codec_preset(&analog_list);
4697 module_init(patch_analog_init)
4698 module_exit(patch_analog_exit)