2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 struct snd_kcontrol_new *mixers[5];
35 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb *init_verbs[5]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs;
42 struct hda_multi_out multiout; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd;
47 unsigned int need_dac_fix;
50 unsigned int num_adc_nids;
52 hda_nid_t dig_in_nid; /* digital-in NID; optional */
55 const struct hda_input_mux *input_mux;
56 hda_nid_t *capsrc_nids;
57 unsigned int cur_mux[3];
60 const struct hda_channel_mode *channel_mode;
64 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
66 unsigned int spdif_route;
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg;
70 struct snd_array kctls;
71 struct hda_input_mux private_imux;
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
74 unsigned int jack_present :1;
75 unsigned int inv_jack_detect:1; /* inverted jack-detection */
76 unsigned int inv_eapd:1; /* inverted EAPD implementation */
78 #ifdef CONFIG_SND_HDA_POWER_SAVE
79 struct hda_loopback_check loopback;
81 /* for virtual master */
82 hda_nid_t vmaster_nid;
83 const char **slave_vols;
84 const char **slave_sws;
88 * input MUX handling (common part)
90 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
92 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
93 struct ad198x_spec *spec = codec->spec;
95 return snd_hda_input_mux_info(spec->input_mux, uinfo);
98 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
100 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
101 struct ad198x_spec *spec = codec->spec;
102 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
104 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
108 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
111 struct ad198x_spec *spec = codec->spec;
112 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
114 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
115 spec->capsrc_nids[adc_idx],
116 &spec->cur_mux[adc_idx]);
120 * initialization (common callbacks)
122 static int ad198x_init(struct hda_codec *codec)
124 struct ad198x_spec *spec = codec->spec;
127 for (i = 0; i < spec->num_init_verbs; i++)
128 snd_hda_sequence_write(codec, spec->init_verbs[i]);
132 static const char *ad_slave_vols[] = {
133 "Front Playback Volume",
134 "Surround Playback Volume",
135 "Center Playback Volume",
136 "LFE Playback Volume",
137 "Side Playback Volume",
138 "Headphone Playback Volume",
139 "Mono Playback Volume",
140 "Speaker Playback Volume",
141 "IEC958 Playback Volume",
145 static const char *ad_slave_sws[] = {
146 "Front Playback Switch",
147 "Surround Playback Switch",
148 "Center Playback Switch",
149 "LFE Playback Switch",
150 "Side Playback Switch",
151 "Headphone Playback Switch",
152 "Mono Playback Switch",
153 "Speaker Playback Switch",
154 "IEC958 Playback Switch",
158 static void ad198x_free_kctls(struct hda_codec *codec);
160 #ifdef CONFIG_SND_HDA_INPUT_BEEP
161 /* additional beep mixers; the actual parameters are overwritten at build */
162 static struct snd_kcontrol_new ad_beep_mixer[] = {
163 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
164 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
168 #define set_beep_amp(spec, nid, idx, dir) \
169 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
171 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
174 static int ad198x_build_controls(struct hda_codec *codec)
176 struct ad198x_spec *spec = codec->spec;
177 struct snd_kcontrol *kctl;
181 for (i = 0; i < spec->num_mixers; i++) {
182 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
186 if (spec->multiout.dig_out_nid) {
187 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
190 err = snd_hda_create_spdif_share_sw(codec,
194 spec->multiout.share_spdif = 1;
196 if (spec->dig_in_nid) {
197 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
202 /* create beep controls if needed */
203 #ifdef CONFIG_SND_HDA_INPUT_BEEP
204 if (spec->beep_amp) {
205 struct snd_kcontrol_new *knew;
206 for (knew = ad_beep_mixer; knew->name; knew++) {
207 struct snd_kcontrol *kctl;
208 kctl = snd_ctl_new1(knew, codec);
211 kctl->private_value = spec->beep_amp;
212 err = snd_hda_ctl_add(codec, 0, kctl);
219 /* if we have no master control, let's create it */
220 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
221 unsigned int vmaster_tlv[4];
222 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
223 HDA_OUTPUT, vmaster_tlv);
224 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
227 spec->slave_vols : ad_slave_vols));
231 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
232 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
235 spec->slave_sws : ad_slave_sws));
240 ad198x_free_kctls(codec); /* no longer needed */
242 /* assign Capture Source enums to NID */
243 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
245 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
246 for (i = 0; kctl && i < kctl->count; i++) {
247 err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids,
248 spec->input_mux->num_items);
253 /* assign IEC958 enums to NID */
254 kctl = snd_hda_find_mixer_ctl(codec,
255 SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
257 err = snd_hda_add_nid(codec, kctl, 0,
258 spec->multiout.dig_out_nid);
266 #ifdef CONFIG_SND_HDA_POWER_SAVE
267 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
269 struct ad198x_spec *spec = codec->spec;
270 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
275 * Analog playback callbacks
277 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
278 struct hda_codec *codec,
279 struct snd_pcm_substream *substream)
281 struct ad198x_spec *spec = codec->spec;
282 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
286 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
287 struct hda_codec *codec,
288 unsigned int stream_tag,
290 struct snd_pcm_substream *substream)
292 struct ad198x_spec *spec = codec->spec;
293 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
297 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
298 struct hda_codec *codec,
299 struct snd_pcm_substream *substream)
301 struct ad198x_spec *spec = codec->spec;
302 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
308 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
309 struct hda_codec *codec,
310 struct snd_pcm_substream *substream)
312 struct ad198x_spec *spec = codec->spec;
313 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
316 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
317 struct hda_codec *codec,
318 struct snd_pcm_substream *substream)
320 struct ad198x_spec *spec = codec->spec;
321 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
324 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
325 struct hda_codec *codec,
326 unsigned int stream_tag,
328 struct snd_pcm_substream *substream)
330 struct ad198x_spec *spec = codec->spec;
331 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
335 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
336 struct hda_codec *codec,
337 struct snd_pcm_substream *substream)
339 struct ad198x_spec *spec = codec->spec;
340 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
346 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
347 struct hda_codec *codec,
348 unsigned int stream_tag,
350 struct snd_pcm_substream *substream)
352 struct ad198x_spec *spec = codec->spec;
353 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
354 stream_tag, 0, format);
358 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
359 struct hda_codec *codec,
360 struct snd_pcm_substream *substream)
362 struct ad198x_spec *spec = codec->spec;
363 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
370 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
373 .channels_max = 6, /* changed later */
374 .nid = 0, /* fill later */
376 .open = ad198x_playback_pcm_open,
377 .prepare = ad198x_playback_pcm_prepare,
378 .cleanup = ad198x_playback_pcm_cleanup
382 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
386 .nid = 0, /* fill later */
388 .prepare = ad198x_capture_pcm_prepare,
389 .cleanup = ad198x_capture_pcm_cleanup
393 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
397 .nid = 0, /* fill later */
399 .open = ad198x_dig_playback_pcm_open,
400 .close = ad198x_dig_playback_pcm_close,
401 .prepare = ad198x_dig_playback_pcm_prepare,
402 .cleanup = ad198x_dig_playback_pcm_cleanup
406 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
410 /* NID is set in alc_build_pcms */
413 static int ad198x_build_pcms(struct hda_codec *codec)
415 struct ad198x_spec *spec = codec->spec;
416 struct hda_pcm *info = spec->pcm_rec;
419 codec->pcm_info = info;
421 info->name = "AD198x Analog";
422 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
423 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
424 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
425 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
426 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
427 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
429 if (spec->multiout.dig_out_nid) {
432 info->name = "AD198x Digital";
433 info->pcm_type = HDA_PCM_TYPE_SPDIF;
434 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
435 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
436 if (spec->dig_in_nid) {
437 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
438 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
445 static void ad198x_free_kctls(struct hda_codec *codec)
447 struct ad198x_spec *spec = codec->spec;
449 if (spec->kctls.list) {
450 struct snd_kcontrol_new *kctl = spec->kctls.list;
452 for (i = 0; i < spec->kctls.used; i++)
455 snd_array_free(&spec->kctls);
458 static void ad198x_free(struct hda_codec *codec)
460 struct ad198x_spec *spec = codec->spec;
465 ad198x_free_kctls(codec);
467 snd_hda_detach_beep_device(codec);
470 static struct hda_codec_ops ad198x_patch_ops = {
471 .build_controls = ad198x_build_controls,
472 .build_pcms = ad198x_build_pcms,
475 #ifdef CONFIG_SND_HDA_POWER_SAVE
476 .check_power_status = ad198x_check_power_status,
483 * the private value = nid
485 #define ad198x_eapd_info snd_ctl_boolean_mono_info
487 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
488 struct snd_ctl_elem_value *ucontrol)
490 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
491 struct ad198x_spec *spec = codec->spec;
493 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
495 ucontrol->value.integer.value[0] = spec->cur_eapd;
499 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
500 struct snd_ctl_elem_value *ucontrol)
502 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
503 struct ad198x_spec *spec = codec->spec;
504 hda_nid_t nid = kcontrol->private_value & 0xff;
506 eapd = !!ucontrol->value.integer.value[0];
509 if (eapd == spec->cur_eapd)
511 spec->cur_eapd = eapd;
512 snd_hda_codec_write_cache(codec, nid,
513 0, AC_VERB_SET_EAPD_BTLENABLE,
518 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
519 struct snd_ctl_elem_info *uinfo);
520 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_value *ucontrol);
522 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
523 struct snd_ctl_elem_value *ucontrol);
530 #define AD1986A_SPDIF_OUT 0x02
531 #define AD1986A_FRONT_DAC 0x03
532 #define AD1986A_SURR_DAC 0x04
533 #define AD1986A_CLFE_DAC 0x05
534 #define AD1986A_ADC 0x06
536 static hda_nid_t ad1986a_dac_nids[3] = {
537 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
539 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
540 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
542 static struct hda_input_mux ad1986a_capture_source = {
556 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
557 .ops = &snd_hda_bind_vol,
559 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
560 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
561 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
566 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
567 .ops = &snd_hda_bind_sw,
569 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
570 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
571 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
579 static struct snd_kcontrol_new ad1986a_mixers[] = {
581 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
583 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
584 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
585 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
586 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
587 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
588 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
589 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
590 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
591 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
592 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
593 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
594 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
595 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
596 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
597 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
598 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
599 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
600 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
601 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
602 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
603 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
604 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
605 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
606 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
607 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
609 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
610 .name = "Capture Source",
611 .info = ad198x_mux_enum_info,
612 .get = ad198x_mux_enum_get,
613 .put = ad198x_mux_enum_put,
615 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
619 /* additional mixers for 3stack mode */
620 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
622 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
623 .name = "Channel Mode",
624 .info = ad198x_ch_mode_info,
625 .get = ad198x_ch_mode_get,
626 .put = ad198x_ch_mode_put,
631 /* laptop model - 2ch only */
632 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
634 /* master controls both pins 0x1a and 0x1b */
635 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
636 .ops = &snd_hda_bind_vol,
638 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
639 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
644 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
645 .ops = &snd_hda_bind_sw,
647 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
648 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
653 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
654 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
655 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
656 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
657 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
658 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
659 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
660 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
661 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
662 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
665 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
666 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
668 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
669 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
670 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
671 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
673 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
674 .name = "Capture Source",
675 .info = ad198x_mux_enum_info,
676 .get = ad198x_mux_enum_get,
677 .put = ad198x_mux_enum_put,
682 /* laptop-eapd model - 2ch only */
684 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
688 { "Internal Mic", 0x4 },
693 static struct hda_input_mux ad1986a_automic_capture_source = {
701 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
702 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
703 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
707 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
708 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
709 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
710 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
711 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
712 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
713 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
714 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
716 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
717 .name = "Capture Source",
718 .info = ad198x_mux_enum_info,
719 .get = ad198x_mux_enum_get,
720 .put = ad198x_mux_enum_put,
723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724 .name = "External Amplifier",
725 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
726 .info = ad198x_eapd_info,
727 .get = ad198x_eapd_get,
728 .put = ad198x_eapd_put,
729 .private_value = 0x1b, /* port-D */
734 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
735 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
736 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
740 /* re-connect the mic boost input according to the jack sensing */
741 static void ad1986a_automic(struct hda_codec *codec)
743 unsigned int present;
744 present = snd_hda_jack_detect(codec, 0x1f);
745 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
746 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
750 #define AD1986A_MIC_EVENT 0x36
752 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
755 if ((res >> 26) != AD1986A_MIC_EVENT)
757 ad1986a_automic(codec);
760 static int ad1986a_automic_init(struct hda_codec *codec)
763 ad1986a_automic(codec);
767 /* laptop-automute - 2ch only */
769 static void ad1986a_update_hp(struct hda_codec *codec)
771 struct ad198x_spec *spec = codec->spec;
774 if (spec->jack_present)
775 mute = HDA_AMP_MUTE; /* mute internal speaker */
777 /* unmute internal speaker if necessary */
778 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
779 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
783 static void ad1986a_hp_automute(struct hda_codec *codec)
785 struct ad198x_spec *spec = codec->spec;
787 spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
788 if (spec->inv_jack_detect)
789 spec->jack_present = !spec->jack_present;
790 ad1986a_update_hp(codec);
793 #define AD1986A_HP_EVENT 0x37
795 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
797 if ((res >> 26) != AD1986A_HP_EVENT)
799 ad1986a_hp_automute(codec);
802 static int ad1986a_hp_init(struct hda_codec *codec)
805 ad1986a_hp_automute(codec);
809 /* bind hp and internal speaker mute (with plug check) */
810 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
811 struct snd_ctl_elem_value *ucontrol)
813 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
814 long *valp = ucontrol->value.integer.value;
817 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
819 valp[0] ? 0 : HDA_AMP_MUTE);
820 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
822 valp[1] ? 0 : HDA_AMP_MUTE);
824 ad1986a_update_hp(codec);
828 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
829 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
832 .name = "Master Playback Switch",
833 .subdevice = HDA_SUBDEV_AMP_FLAG,
834 .info = snd_hda_mixer_amp_switch_info,
835 .get = snd_hda_mixer_amp_switch_get,
836 .put = ad1986a_hp_master_sw_put,
837 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
844 * initialization verbs
846 static struct hda_verb ad1986a_init_verbs[] = {
847 /* Front, Surround, CLFE DAC; mute as default */
848 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
849 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
850 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
852 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
853 /* HP, Line-Out, Surround, CLFE selectors */
854 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
855 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
856 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
857 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
859 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
860 /* Mic selector: Mic 1/2 pin */
861 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
862 /* Line-in selector: Line-in */
863 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
865 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
866 /* Record selector: mic */
867 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
868 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
869 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
870 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
871 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
872 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
873 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
875 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
876 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
877 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
878 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
879 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
880 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
881 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
883 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
884 /* Front, Surround, CLFE Pins */
885 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
886 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
887 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
889 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
891 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
892 /* Line, Aux, CD, Beep-In Pin */
893 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
894 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
895 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
896 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
897 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
901 static struct hda_verb ad1986a_ch2_init[] = {
902 /* Surround out -> Line In */
903 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
904 /* Line-in selectors */
905 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
907 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
908 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
909 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
913 static struct hda_verb ad1986a_ch4_init[] = {
914 /* Surround out -> Surround */
915 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
916 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
918 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
919 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
923 static struct hda_verb ad1986a_ch6_init[] = {
924 /* Surround out -> Surround out */
925 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
926 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
928 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
929 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
933 static struct hda_channel_mode ad1986a_modes[3] = {
934 { 2, ad1986a_ch2_init },
935 { 4, ad1986a_ch4_init },
936 { 6, ad1986a_ch6_init },
939 /* eapd initialization */
940 static struct hda_verb ad1986a_eapd_init_verbs[] = {
941 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
945 static struct hda_verb ad1986a_automic_verbs[] = {
946 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
947 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
948 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
949 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
950 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
954 /* Ultra initialization */
955 static struct hda_verb ad1986a_ultra_init[] = {
956 /* eapd initialization */
957 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
959 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
960 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
961 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
965 /* pin sensing on HP jack */
966 static struct hda_verb ad1986a_hp_init_verbs[] = {
967 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
971 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
975 case AD1986A_HP_EVENT:
976 ad1986a_hp_automute(codec);
978 case AD1986A_MIC_EVENT:
979 ad1986a_automic(codec);
984 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
987 ad1986a_hp_automute(codec);
988 ad1986a_automic(codec);
999 AD1986A_LAPTOP_AUTOMUTE,
1002 AD1986A_SAMSUNG_P50,
1006 static const char *ad1986a_models[AD1986A_MODELS] = {
1007 [AD1986A_6STACK] = "6stack",
1008 [AD1986A_3STACK] = "3stack",
1009 [AD1986A_LAPTOP] = "laptop",
1010 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
1011 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1012 [AD1986A_ULTRA] = "ultra",
1013 [AD1986A_SAMSUNG] = "samsung",
1014 [AD1986A_SAMSUNG_P50] = "samsung-p50",
1017 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1018 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1019 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1020 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1021 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1022 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1023 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1024 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1025 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1026 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1027 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1028 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1029 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1030 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1031 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1032 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1033 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1034 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
1035 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1036 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1037 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1038 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1039 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1040 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1041 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1042 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1043 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1044 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1048 #ifdef CONFIG_SND_HDA_POWER_SAVE
1049 static struct hda_amp_list ad1986a_loopbacks[] = {
1050 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1051 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1052 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1053 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1054 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1059 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1061 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1062 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1065 static int patch_ad1986a(struct hda_codec *codec)
1067 struct ad198x_spec *spec;
1068 int err, board_config;
1070 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1076 err = snd_hda_attach_beep_device(codec, 0x19);
1081 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1083 spec->multiout.max_channels = 6;
1084 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1085 spec->multiout.dac_nids = ad1986a_dac_nids;
1086 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1087 spec->num_adc_nids = 1;
1088 spec->adc_nids = ad1986a_adc_nids;
1089 spec->capsrc_nids = ad1986a_capsrc_nids;
1090 spec->input_mux = &ad1986a_capture_source;
1091 spec->num_mixers = 1;
1092 spec->mixers[0] = ad1986a_mixers;
1093 spec->num_init_verbs = 1;
1094 spec->init_verbs[0] = ad1986a_init_verbs;
1095 #ifdef CONFIG_SND_HDA_POWER_SAVE
1096 spec->loopback.amplist = ad1986a_loopbacks;
1098 spec->vmaster_nid = 0x1b;
1099 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1101 codec->patch_ops = ad198x_patch_ops;
1103 /* override some parameters */
1104 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1107 switch (board_config) {
1108 case AD1986A_3STACK:
1109 spec->num_mixers = 2;
1110 spec->mixers[1] = ad1986a_3st_mixers;
1111 spec->num_init_verbs = 2;
1112 spec->init_verbs[1] = ad1986a_ch2_init;
1113 spec->channel_mode = ad1986a_modes;
1114 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1115 spec->need_dac_fix = 1;
1116 spec->multiout.max_channels = 2;
1117 spec->multiout.num_dacs = 1;
1119 case AD1986A_LAPTOP:
1120 spec->mixers[0] = ad1986a_laptop_mixers;
1121 spec->multiout.max_channels = 2;
1122 spec->multiout.num_dacs = 1;
1123 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1125 case AD1986A_LAPTOP_EAPD:
1126 spec->num_mixers = 3;
1127 spec->mixers[0] = ad1986a_laptop_master_mixers;
1128 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1129 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1130 spec->num_init_verbs = 2;
1131 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1132 spec->multiout.max_channels = 2;
1133 spec->multiout.num_dacs = 1;
1134 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1135 if (!is_jack_available(codec, 0x25))
1136 spec->multiout.dig_out_nid = 0;
1137 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1139 case AD1986A_SAMSUNG:
1140 spec->num_mixers = 2;
1141 spec->mixers[0] = ad1986a_laptop_master_mixers;
1142 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1143 spec->num_init_verbs = 3;
1144 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1145 spec->init_verbs[2] = ad1986a_automic_verbs;
1146 spec->multiout.max_channels = 2;
1147 spec->multiout.num_dacs = 1;
1148 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1149 if (!is_jack_available(codec, 0x25))
1150 spec->multiout.dig_out_nid = 0;
1151 spec->input_mux = &ad1986a_automic_capture_source;
1152 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1153 codec->patch_ops.init = ad1986a_automic_init;
1155 case AD1986A_SAMSUNG_P50:
1156 spec->num_mixers = 2;
1157 spec->mixers[0] = ad1986a_automute_master_mixers;
1158 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1159 spec->num_init_verbs = 4;
1160 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1161 spec->init_verbs[2] = ad1986a_automic_verbs;
1162 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1163 spec->multiout.max_channels = 2;
1164 spec->multiout.num_dacs = 1;
1165 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1166 if (!is_jack_available(codec, 0x25))
1167 spec->multiout.dig_out_nid = 0;
1168 spec->input_mux = &ad1986a_automic_capture_source;
1169 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1170 codec->patch_ops.init = ad1986a_samsung_p50_init;
1172 case AD1986A_LAPTOP_AUTOMUTE:
1173 spec->num_mixers = 3;
1174 spec->mixers[0] = ad1986a_automute_master_mixers;
1175 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1176 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1177 spec->num_init_verbs = 3;
1178 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1179 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1180 spec->multiout.max_channels = 2;
1181 spec->multiout.num_dacs = 1;
1182 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1183 if (!is_jack_available(codec, 0x25))
1184 spec->multiout.dig_out_nid = 0;
1185 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1186 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1187 codec->patch_ops.init = ad1986a_hp_init;
1188 /* Lenovo N100 seems to report the reversed bit
1189 * for HP jack-sensing
1191 spec->inv_jack_detect = 1;
1194 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1195 spec->num_init_verbs = 2;
1196 spec->init_verbs[1] = ad1986a_ultra_init;
1197 spec->multiout.max_channels = 2;
1198 spec->multiout.num_dacs = 1;
1199 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1200 spec->multiout.dig_out_nid = 0;
1204 /* AD1986A has a hardware problem that it can't share a stream
1205 * with multiple output pins. The copy of front to surrounds
1206 * causes noisy or silent outputs at a certain timing, e.g.
1207 * changing the volume.
1208 * So, let's disable the shared stream.
1210 spec->multiout.no_share_stream = 1;
1219 #define AD1983_SPDIF_OUT 0x02
1220 #define AD1983_DAC 0x03
1221 #define AD1983_ADC 0x04
1223 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1224 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1225 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1227 static struct hda_input_mux ad1983_capture_source = {
1233 { "Mix Mono", 0x3 },
1238 * SPDIF playback route
1240 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1242 static char *texts[] = { "PCM", "ADC" };
1244 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1246 uinfo->value.enumerated.items = 2;
1247 if (uinfo->value.enumerated.item > 1)
1248 uinfo->value.enumerated.item = 1;
1249 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1253 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1255 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1256 struct ad198x_spec *spec = codec->spec;
1258 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1262 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1264 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1265 struct ad198x_spec *spec = codec->spec;
1267 if (ucontrol->value.enumerated.item[0] > 1)
1269 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1270 spec->spdif_route = ucontrol->value.enumerated.item[0];
1271 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1272 AC_VERB_SET_CONNECT_SEL,
1279 static struct snd_kcontrol_new ad1983_mixers[] = {
1280 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1281 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1282 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1283 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1284 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1285 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1286 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1287 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1288 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1289 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1290 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1291 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1292 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1293 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1294 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1296 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1297 .name = "Capture Source",
1298 .info = ad198x_mux_enum_info,
1299 .get = ad198x_mux_enum_get,
1300 .put = ad198x_mux_enum_put,
1303 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1304 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1305 .info = ad1983_spdif_route_info,
1306 .get = ad1983_spdif_route_get,
1307 .put = ad1983_spdif_route_put,
1312 static struct hda_verb ad1983_init_verbs[] = {
1313 /* Front, HP, Mono; mute as default */
1314 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1315 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1316 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1317 /* Beep, PCM, Mic, Line-In: mute */
1318 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1319 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1320 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1321 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1322 /* Front, HP selectors; from Mix */
1323 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1324 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1325 /* Mono selector; from Mix */
1326 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1327 /* Mic selector; Mic */
1328 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1329 /* Line-in selector: Line-in */
1330 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1331 /* Mic boost: 0dB */
1332 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1333 /* Record selector: mic */
1334 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1335 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1336 /* SPDIF route: PCM */
1337 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1339 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1341 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1343 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1345 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1347 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1351 #ifdef CONFIG_SND_HDA_POWER_SAVE
1352 static struct hda_amp_list ad1983_loopbacks[] = {
1353 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1354 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1359 static int patch_ad1983(struct hda_codec *codec)
1361 struct ad198x_spec *spec;
1364 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1370 err = snd_hda_attach_beep_device(codec, 0x10);
1375 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1377 spec->multiout.max_channels = 2;
1378 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1379 spec->multiout.dac_nids = ad1983_dac_nids;
1380 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1381 spec->num_adc_nids = 1;
1382 spec->adc_nids = ad1983_adc_nids;
1383 spec->capsrc_nids = ad1983_capsrc_nids;
1384 spec->input_mux = &ad1983_capture_source;
1385 spec->num_mixers = 1;
1386 spec->mixers[0] = ad1983_mixers;
1387 spec->num_init_verbs = 1;
1388 spec->init_verbs[0] = ad1983_init_verbs;
1389 spec->spdif_route = 0;
1390 #ifdef CONFIG_SND_HDA_POWER_SAVE
1391 spec->loopback.amplist = ad1983_loopbacks;
1393 spec->vmaster_nid = 0x05;
1395 codec->patch_ops = ad198x_patch_ops;
1402 * AD1981 HD specific
1405 #define AD1981_SPDIF_OUT 0x02
1406 #define AD1981_DAC 0x03
1407 #define AD1981_ADC 0x04
1409 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1410 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1411 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1413 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1414 static struct hda_input_mux ad1981_capture_source = {
1417 { "Front Mic", 0x0 },
1420 { "Mix Mono", 0x3 },
1427 static struct snd_kcontrol_new ad1981_mixers[] = {
1428 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1429 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1430 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1431 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1432 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1433 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1434 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1435 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1436 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1437 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1438 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1439 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1440 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1441 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1442 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1443 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1444 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1445 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1446 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1447 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1448 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1449 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1451 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1452 .name = "Capture Source",
1453 .info = ad198x_mux_enum_info,
1454 .get = ad198x_mux_enum_get,
1455 .put = ad198x_mux_enum_put,
1457 /* identical with AD1983 */
1459 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1460 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1461 .info = ad1983_spdif_route_info,
1462 .get = ad1983_spdif_route_get,
1463 .put = ad1983_spdif_route_put,
1468 static struct hda_verb ad1981_init_verbs[] = {
1469 /* Front, HP, Mono; mute as default */
1470 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1471 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1472 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1473 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1474 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1475 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1476 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1477 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1478 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1479 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1480 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1481 /* Front, HP selectors; from Mix */
1482 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1483 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1484 /* Mono selector; from Mix */
1485 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1486 /* Mic Mixer; select Front Mic */
1487 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1488 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1489 /* Mic boost: 0dB */
1490 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1491 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1492 /* Record selector: Front mic */
1493 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1494 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1495 /* SPDIF route: PCM */
1496 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1498 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1500 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1502 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1503 /* Front & Rear Mic Pins */
1504 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1505 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1507 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1509 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1510 /* Line-Out as Input: disabled */
1511 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1515 #ifdef CONFIG_SND_HDA_POWER_SAVE
1516 static struct hda_amp_list ad1981_loopbacks[] = {
1517 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1518 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1519 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1520 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1521 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1527 * Patch for HP nx6320
1529 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1530 * speaker output enabled _and_ mute-LED off.
1533 #define AD1981_HP_EVENT 0x37
1534 #define AD1981_MIC_EVENT 0x38
1536 static struct hda_verb ad1981_hp_init_verbs[] = {
1537 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1538 /* pin sensing on HP and Mic jacks */
1539 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1540 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1544 /* turn on/off EAPD (+ mute HP) as a master switch */
1545 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1546 struct snd_ctl_elem_value *ucontrol)
1548 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1549 struct ad198x_spec *spec = codec->spec;
1551 if (! ad198x_eapd_put(kcontrol, ucontrol))
1553 /* change speaker pin appropriately */
1554 snd_hda_codec_write(codec, 0x05, 0,
1555 AC_VERB_SET_PIN_WIDGET_CONTROL,
1556 spec->cur_eapd ? PIN_OUT : 0);
1557 /* toggle HP mute appropriately */
1558 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1560 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1564 /* bind volumes of both NID 0x05 and 0x06 */
1565 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1566 .ops = &snd_hda_bind_vol,
1568 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1569 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1574 /* mute internal speaker if HP is plugged */
1575 static void ad1981_hp_automute(struct hda_codec *codec)
1577 unsigned int present;
1579 present = snd_hda_jack_detect(codec, 0x06);
1580 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1581 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1584 /* toggle input of built-in and mic jack appropriately */
1585 static void ad1981_hp_automic(struct hda_codec *codec)
1587 static struct hda_verb mic_jack_on[] = {
1588 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1589 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1592 static struct hda_verb mic_jack_off[] = {
1593 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1594 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1597 unsigned int present;
1599 present = snd_hda_jack_detect(codec, 0x08);
1601 snd_hda_sequence_write(codec, mic_jack_on);
1603 snd_hda_sequence_write(codec, mic_jack_off);
1606 /* unsolicited event for HP jack sensing */
1607 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1612 case AD1981_HP_EVENT:
1613 ad1981_hp_automute(codec);
1615 case AD1981_MIC_EVENT:
1616 ad1981_hp_automic(codec);
1621 static struct hda_input_mux ad1981_hp_capture_source = {
1625 { "Docking-Station", 0x1 },
1630 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1631 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1633 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1634 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1635 .name = "Master Playback Switch",
1636 .info = ad198x_eapd_info,
1637 .get = ad198x_eapd_get,
1638 .put = ad1981_hp_master_sw_put,
1639 .private_value = 0x05,
1641 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1642 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1644 /* FIXME: analog mic/line loopback doesn't work with my tests...
1645 * (although recording is OK)
1647 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1648 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1649 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1650 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1651 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1652 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1653 /* FIXME: does this laptop have analog CD connection? */
1654 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1655 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1657 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1658 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1659 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1660 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1662 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1663 .name = "Capture Source",
1664 .info = ad198x_mux_enum_info,
1665 .get = ad198x_mux_enum_get,
1666 .put = ad198x_mux_enum_put,
1671 /* initialize jack-sensing, too */
1672 static int ad1981_hp_init(struct hda_codec *codec)
1675 ad1981_hp_automute(codec);
1676 ad1981_hp_automic(codec);
1680 /* configuration for Toshiba Laptops */
1681 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1682 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1683 /* pin sensing on HP and Mic jacks */
1684 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1685 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1689 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1690 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1691 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1695 /* configuration for Lenovo Thinkpad T60 */
1696 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1697 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1698 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1699 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1700 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1701 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1702 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1703 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1704 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1705 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1706 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1707 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1709 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1710 .name = "Capture Source",
1711 .info = ad198x_mux_enum_info,
1712 .get = ad198x_mux_enum_get,
1713 .put = ad198x_mux_enum_put,
1715 /* identical with AD1983 */
1717 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1718 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1719 .info = ad1983_spdif_route_info,
1720 .get = ad1983_spdif_route_get,
1721 .put = ad1983_spdif_route_put,
1726 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1744 static const char *ad1981_models[AD1981_MODELS] = {
1746 [AD1981_THINKPAD] = "thinkpad",
1747 [AD1981_BASIC] = "basic",
1748 [AD1981_TOSHIBA] = "toshiba"
1751 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1752 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1753 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1755 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1756 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1757 /* Lenovo Thinkpad T60/X60/Z6xx */
1758 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1759 /* HP nx6320 (reversed SSID, H/W bug) */
1760 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1764 static int patch_ad1981(struct hda_codec *codec)
1766 struct ad198x_spec *spec;
1767 int err, board_config;
1769 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1775 err = snd_hda_attach_beep_device(codec, 0x10);
1780 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1782 spec->multiout.max_channels = 2;
1783 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1784 spec->multiout.dac_nids = ad1981_dac_nids;
1785 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1786 spec->num_adc_nids = 1;
1787 spec->adc_nids = ad1981_adc_nids;
1788 spec->capsrc_nids = ad1981_capsrc_nids;
1789 spec->input_mux = &ad1981_capture_source;
1790 spec->num_mixers = 1;
1791 spec->mixers[0] = ad1981_mixers;
1792 spec->num_init_verbs = 1;
1793 spec->init_verbs[0] = ad1981_init_verbs;
1794 spec->spdif_route = 0;
1795 #ifdef CONFIG_SND_HDA_POWER_SAVE
1796 spec->loopback.amplist = ad1981_loopbacks;
1798 spec->vmaster_nid = 0x05;
1800 codec->patch_ops = ad198x_patch_ops;
1802 /* override some parameters */
1803 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1806 switch (board_config) {
1808 spec->mixers[0] = ad1981_hp_mixers;
1809 spec->num_init_verbs = 2;
1810 spec->init_verbs[1] = ad1981_hp_init_verbs;
1811 spec->multiout.dig_out_nid = 0;
1812 spec->input_mux = &ad1981_hp_capture_source;
1814 codec->patch_ops.init = ad1981_hp_init;
1815 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1816 /* set the upper-limit for mixer amp to 0dB for avoiding the
1817 * possible damage by overloading
1819 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1820 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1821 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1822 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1823 (1 << AC_AMPCAP_MUTE_SHIFT));
1825 case AD1981_THINKPAD:
1826 spec->mixers[0] = ad1981_thinkpad_mixers;
1827 spec->input_mux = &ad1981_thinkpad_capture_source;
1829 case AD1981_TOSHIBA:
1830 spec->mixers[0] = ad1981_hp_mixers;
1831 spec->mixers[1] = ad1981_toshiba_mixers;
1832 spec->num_init_verbs = 2;
1833 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1834 spec->multiout.dig_out_nid = 0;
1835 spec->input_mux = &ad1981_hp_capture_source;
1836 codec->patch_ops.init = ad1981_hp_init;
1837 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1847 * Output pins and routes
1849 * Pin Mix Sel DAC (*)
1850 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1851 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1852 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1853 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1854 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1855 * port-F 0x16 (mute) <- 0x2a <- 06
1856 * port-G 0x24 (mute) <- 0x27 <- 05
1857 * port-H 0x25 (mute) <- 0x28 <- 0a
1858 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1860 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1861 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1863 * Input pins and routes
1865 * pin boost mix input # / adc input #
1866 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1867 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1868 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1869 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1870 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1871 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1872 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1873 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1877 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1878 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1880 * Inputs of Analog Mix (0x20)
1881 * 0:Port-B (front mic)
1882 * 1:Port-C/G/H (line-in)
1884 * 3:Port-D (line-in/2)
1885 * 4:Port-E/G/H (mic-in)
1886 * 5:Port-F (mic2-in)
1892 * 1:Port-B (front mic-in)
1893 * 2:Port-C (line-in)
1894 * 3:Port-F (mic2-in)
1899 * 8:Port-D (line-in/2)
1902 * Proposed pin assignments by the datasheet
1905 * Port-A front headphone
1915 * Port-A front headphone
1917 * C rear line-in/surround
1919 * E rear mic-in/CLFE
1925 * D internal speaker (with EAPD)
1926 * E/F quad mic array
1942 /* reivision id to check workarounds */
1943 #define AD1988A_REV2 0x100200
1945 #define is_rev2(codec) \
1946 ((codec)->vendor_id == 0x11d41988 && \
1947 (codec)->revision_id == AD1988A_REV2)
1953 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1954 0x04, 0x06, 0x05, 0x0a
1957 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1961 /* for AD1988A revision-2, DAC2-4 are swapped */
1962 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1963 0x04, 0x05, 0x0a, 0x06
1966 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1970 static hda_nid_t ad1988_adc_nids[3] = {
1974 static hda_nid_t ad1988_capsrc_nids[3] = {
1978 #define AD1988_SPDIF_OUT 0x02
1979 #define AD1988_SPDIF_OUT_HDMI 0x0b
1980 #define AD1988_SPDIF_IN 0x07
1982 static hda_nid_t ad1989b_slave_dig_outs[] = {
1983 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
1986 static struct hda_input_mux ad1988_6stack_capture_source = {
1989 { "Front Mic", 0x1 }, /* port-B */
1990 { "Line", 0x2 }, /* port-C */
1991 { "Mic", 0x4 }, /* port-E */
1997 static struct hda_input_mux ad1988_laptop_capture_source = {
2000 { "Mic/Line", 0x1 }, /* port-B */
2008 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2009 struct snd_ctl_elem_info *uinfo)
2011 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2012 struct ad198x_spec *spec = codec->spec;
2013 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2014 spec->num_channel_mode);
2017 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2018 struct snd_ctl_elem_value *ucontrol)
2020 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2021 struct ad198x_spec *spec = codec->spec;
2022 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2023 spec->num_channel_mode, spec->multiout.max_channels);
2026 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2027 struct snd_ctl_elem_value *ucontrol)
2029 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2030 struct ad198x_spec *spec = codec->spec;
2031 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2032 spec->num_channel_mode,
2033 &spec->multiout.max_channels);
2034 if (err >= 0 && spec->need_dac_fix)
2035 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2040 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2041 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2042 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2043 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2044 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2045 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2049 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2050 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2051 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2052 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2053 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2054 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2058 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2059 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2060 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2061 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2062 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2063 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2064 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2065 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2067 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2068 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2069 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2070 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2071 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2072 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2073 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2074 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2076 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2077 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2079 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2080 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2086 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2087 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2088 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2089 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2090 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2094 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2095 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2096 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2097 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2098 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2102 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2103 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2104 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2105 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2106 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2107 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2108 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2110 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2111 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2112 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2113 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2114 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2115 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2116 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2117 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2119 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2120 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2122 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2123 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2125 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2126 .name = "Channel Mode",
2127 .info = ad198x_ch_mode_info,
2128 .get = ad198x_ch_mode_get,
2129 .put = ad198x_ch_mode_put,
2136 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2137 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2138 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2139 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2141 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2142 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2143 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2144 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2145 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2146 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2148 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2149 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2151 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2155 .name = "External Amplifier",
2156 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2157 .info = ad198x_eapd_info,
2158 .get = ad198x_eapd_get,
2159 .put = ad198x_eapd_put,
2160 .private_value = 0x12, /* port-D */
2167 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2168 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2169 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2170 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2171 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2172 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2173 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2175 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2176 /* The multiple "Capture Source" controls confuse alsamixer
2177 * So call somewhat different..
2179 /* .name = "Capture Source", */
2180 .name = "Input Source",
2182 .info = ad198x_mux_enum_info,
2183 .get = ad198x_mux_enum_get,
2184 .put = ad198x_mux_enum_put,
2189 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2190 struct snd_ctl_elem_info *uinfo)
2192 static char *texts[] = {
2193 "PCM", "ADC1", "ADC2", "ADC3"
2195 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2197 uinfo->value.enumerated.items = 4;
2198 if (uinfo->value.enumerated.item >= 4)
2199 uinfo->value.enumerated.item = 3;
2200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2204 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2205 struct snd_ctl_elem_value *ucontrol)
2207 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2210 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2213 ucontrol->value.enumerated.item[0] = 0;
2215 sel = snd_hda_codec_read(codec, 0x0b, 0,
2216 AC_VERB_GET_CONNECT_SEL, 0);
2221 ucontrol->value.enumerated.item[0] = sel;
2226 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2227 struct snd_ctl_elem_value *ucontrol)
2229 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2230 unsigned int val, sel;
2233 val = ucontrol->value.enumerated.item[0];
2237 sel = snd_hda_codec_read(codec, 0x1d, 0,
2238 AC_VERB_GET_AMP_GAIN_MUTE,
2240 change = sel & 0x80;
2242 snd_hda_codec_write_cache(codec, 0x1d, 0,
2243 AC_VERB_SET_AMP_GAIN_MUTE,
2245 snd_hda_codec_write_cache(codec, 0x1d, 0,
2246 AC_VERB_SET_AMP_GAIN_MUTE,
2250 sel = snd_hda_codec_read(codec, 0x1d, 0,
2251 AC_VERB_GET_AMP_GAIN_MUTE,
2252 AC_AMP_GET_INPUT | 0x01);
2253 change = sel & 0x80;
2255 snd_hda_codec_write_cache(codec, 0x1d, 0,
2256 AC_VERB_SET_AMP_GAIN_MUTE,
2258 snd_hda_codec_write_cache(codec, 0x1d, 0,
2259 AC_VERB_SET_AMP_GAIN_MUTE,
2262 sel = snd_hda_codec_read(codec, 0x0b, 0,
2263 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2264 change |= sel != val;
2266 snd_hda_codec_write_cache(codec, 0x0b, 0,
2267 AC_VERB_SET_CONNECT_SEL,
2273 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2274 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2276 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2277 .name = "IEC958 Playback Source",
2278 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2279 .info = ad1988_spdif_playback_source_info,
2280 .get = ad1988_spdif_playback_source_get,
2281 .put = ad1988_spdif_playback_source_put,
2286 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2287 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2291 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2292 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2293 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2298 * initialization verbs
2302 * for 6-stack (+dig)
2304 static struct hda_verb ad1988_6stack_init_verbs[] = {
2305 /* Front, Surround, CLFE, side DAC; unmute as default */
2306 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2307 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2308 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2309 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2310 /* Port-A front headphon path */
2311 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2312 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2313 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2314 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2315 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2316 /* Port-D line-out path */
2317 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2318 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2319 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2320 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2321 /* Port-F surround path */
2322 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2323 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2324 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2325 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2326 /* Port-G CLFE path */
2327 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2328 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2329 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2330 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2331 /* Port-H side path */
2332 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2333 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2334 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2335 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2337 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2338 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2339 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2340 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2341 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2342 /* Port-B front mic-in path */
2343 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2344 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2345 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2346 /* Port-C line-in path */
2347 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2348 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2349 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2350 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2351 /* Port-E mic-in path */
2352 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2353 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2354 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2355 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2356 /* Analog CD Input */
2357 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2358 /* Analog Mix output amp */
2359 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2364 static struct hda_verb ad1988_capture_init_verbs[] = {
2365 /* mute analog mix */
2366 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2367 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2368 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2369 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2370 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2371 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2372 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2373 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2374 /* select ADCs - front-mic */
2375 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2376 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2377 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2382 static struct hda_verb ad1988_spdif_init_verbs[] = {
2384 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2385 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2386 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2387 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2389 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2394 /* AD1989 has no ADC -> SPDIF route */
2395 static struct hda_verb ad1989_spdif_init_verbs[] = {
2396 /* SPDIF-1 out pin */
2397 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2398 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2399 /* SPDIF-2/HDMI out pin */
2400 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2401 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2406 * verbs for 3stack (+dig)
2408 static struct hda_verb ad1988_3stack_ch2_init[] = {
2409 /* set port-C to line-in */
2410 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2411 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2412 /* set port-E to mic-in */
2413 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2414 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2418 static struct hda_verb ad1988_3stack_ch6_init[] = {
2419 /* set port-C to surround out */
2420 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2421 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2422 /* set port-E to CLFE out */
2423 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2424 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2428 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2429 { 2, ad1988_3stack_ch2_init },
2430 { 6, ad1988_3stack_ch6_init },
2433 static struct hda_verb ad1988_3stack_init_verbs[] = {
2434 /* Front, Surround, CLFE, side DAC; unmute as default */
2435 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2436 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2437 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2438 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2439 /* Port-A front headphon path */
2440 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2441 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2442 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2443 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2444 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2445 /* Port-D line-out path */
2446 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2447 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2448 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2449 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2451 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2452 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2453 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2454 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2455 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2456 /* Port-B front mic-in path */
2457 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2458 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2459 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2460 /* Port-C line-in/surround path - 6ch mode as default */
2461 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2462 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2463 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2464 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2465 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2466 /* Port-E mic-in/CLFE path - 6ch mode as default */
2467 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2468 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2469 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2470 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2471 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2472 /* mute analog mix */
2473 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2474 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2475 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2476 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2477 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2478 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2479 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2480 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2481 /* select ADCs - front-mic */
2482 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2483 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2484 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2485 /* Analog Mix output amp */
2486 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2491 * verbs for laptop mode (+dig)
2493 static struct hda_verb ad1988_laptop_hp_on[] = {
2494 /* unmute port-A and mute port-D */
2495 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2496 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2499 static struct hda_verb ad1988_laptop_hp_off[] = {
2500 /* mute port-A and unmute port-D */
2501 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2502 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2506 #define AD1988_HP_EVENT 0x01
2508 static struct hda_verb ad1988_laptop_init_verbs[] = {
2509 /* Front, Surround, CLFE, side DAC; unmute as default */
2510 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2511 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2512 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2513 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2514 /* Port-A front headphon path */
2515 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2516 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2517 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2518 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2519 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2520 /* unsolicited event for pin-sense */
2521 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2522 /* Port-D line-out path + EAPD */
2523 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2524 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2525 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2526 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2527 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2529 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2530 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2531 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2532 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2533 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2534 /* Port-B mic-in path */
2535 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2536 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2537 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2538 /* Port-C docking station - try to output */
2539 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2540 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2541 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2542 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2543 /* mute analog mix */
2544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2549 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2550 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2551 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2552 /* select ADCs - mic */
2553 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2554 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2555 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2556 /* Analog Mix output amp */
2557 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2561 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2563 if ((res >> 26) != AD1988_HP_EVENT)
2565 if (snd_hda_jack_detect(codec, 0x11))
2566 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2568 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2571 #ifdef CONFIG_SND_HDA_POWER_SAVE
2572 static struct hda_amp_list ad1988_loopbacks[] = {
2573 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2574 { 0x20, HDA_INPUT, 1 }, /* Line */
2575 { 0x20, HDA_INPUT, 4 }, /* Mic */
2576 { 0x20, HDA_INPUT, 6 }, /* CD */
2582 * Automatic parse of I/O pins from the BIOS configuration
2590 static struct snd_kcontrol_new ad1988_control_templates[] = {
2591 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2592 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2593 HDA_BIND_MUTE(NULL, 0, 0, 0),
2596 /* add dynamic controls */
2597 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2600 struct snd_kcontrol_new *knew;
2602 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2603 knew = snd_array_new(&spec->kctls);
2606 *knew = ad1988_control_templates[type];
2607 knew->name = kstrdup(name, GFP_KERNEL);
2610 if (get_amp_nid_(val))
2611 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2612 knew->private_value = val;
2616 #define AD1988_PIN_CD_NID 0x18
2617 #define AD1988_PIN_BEEP_NID 0x10
2619 static hda_nid_t ad1988_mixer_nids[8] = {
2620 /* A B C D E F G H */
2621 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2624 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2626 static hda_nid_t idx_to_dac[8] = {
2627 /* A B C D E F G H */
2628 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2630 static hda_nid_t idx_to_dac_rev2[8] = {
2631 /* A B C D E F G H */
2632 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2635 return idx_to_dac_rev2[idx];
2637 return idx_to_dac[idx];
2640 static hda_nid_t ad1988_boost_nids[8] = {
2641 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2644 static int ad1988_pin_idx(hda_nid_t nid)
2646 static hda_nid_t ad1988_io_pins[8] = {
2647 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2650 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2651 if (ad1988_io_pins[i] == nid)
2653 return 0; /* should be -1 */
2656 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2658 static int loopback_idx[8] = {
2659 2, 0, 1, 3, 4, 5, 1, 4
2662 case AD1988_PIN_CD_NID:
2665 return loopback_idx[ad1988_pin_idx(nid)];
2669 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2671 static int adc_idx[8] = {
2672 0, 1, 2, 8, 4, 3, 6, 7
2675 case AD1988_PIN_CD_NID:
2678 return adc_idx[ad1988_pin_idx(nid)];
2682 /* fill in the dac_nids table from the parsed pin configuration */
2683 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2684 const struct auto_pin_cfg *cfg)
2686 struct ad198x_spec *spec = codec->spec;
2689 spec->multiout.dac_nids = spec->private_dac_nids;
2691 /* check the pins hardwired to audio widget */
2692 for (i = 0; i < cfg->line_outs; i++) {
2693 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2694 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2696 spec->multiout.num_dacs = cfg->line_outs;
2700 /* add playback controls from the parsed DAC table */
2701 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2702 const struct auto_pin_cfg *cfg)
2705 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2709 for (i = 0; i < cfg->line_outs; i++) {
2710 hda_nid_t dac = spec->multiout.dac_nids[i];
2713 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2716 err = add_control(spec, AD_CTL_WIDGET_VOL,
2717 "Center Playback Volume",
2718 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2721 err = add_control(spec, AD_CTL_WIDGET_VOL,
2722 "LFE Playback Volume",
2723 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2726 err = add_control(spec, AD_CTL_BIND_MUTE,
2727 "Center Playback Switch",
2728 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2731 err = add_control(spec, AD_CTL_BIND_MUTE,
2732 "LFE Playback Switch",
2733 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2737 sprintf(name, "%s Playback Volume", chname[i]);
2738 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2739 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2742 sprintf(name, "%s Playback Switch", chname[i]);
2743 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2744 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2752 /* add playback controls for speaker and HP outputs */
2753 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2756 struct ad198x_spec *spec = codec->spec;
2764 idx = ad1988_pin_idx(pin);
2765 nid = ad1988_idx_to_dac(codec, idx);
2766 /* check whether the corresponding DAC was already taken */
2767 for (i = 0; i < spec->autocfg.line_outs; i++) {
2768 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2769 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2773 if (i >= spec->autocfg.line_outs) {
2774 /* specify the DAC as the extra output */
2775 if (!spec->multiout.hp_nid)
2776 spec->multiout.hp_nid = nid;
2778 spec->multiout.extra_out_nid[0] = nid;
2779 /* control HP volume/switch on the output mixer amp */
2780 sprintf(name, "%s Playback Volume", pfx);
2781 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2782 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2786 nid = ad1988_mixer_nids[idx];
2787 sprintf(name, "%s Playback Switch", pfx);
2788 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2789 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2794 /* create input playback/capture controls for the given pin */
2795 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2796 const char *ctlname, int boost)
2801 sprintf(name, "%s Playback Volume", ctlname);
2802 idx = ad1988_pin_to_loopback_idx(pin);
2803 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2804 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2806 sprintf(name, "%s Playback Switch", ctlname);
2807 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2808 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2812 idx = ad1988_pin_idx(pin);
2813 bnid = ad1988_boost_nids[idx];
2815 sprintf(name, "%s Boost", ctlname);
2816 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2817 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2824 /* create playback/capture controls for input pins */
2825 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2826 const struct auto_pin_cfg *cfg)
2828 struct hda_input_mux *imux = &spec->private_imux;
2831 for (i = 0; i < AUTO_PIN_LAST; i++) {
2832 err = new_analog_input(spec, cfg->input_pins[i],
2833 auto_pin_cfg_labels[i],
2834 i <= AUTO_PIN_FRONT_MIC);
2837 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2838 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2841 imux->items[imux->num_items].label = "Mix";
2842 imux->items[imux->num_items].index = 9;
2845 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2846 "Analog Mix Playback Volume",
2847 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2849 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2850 "Analog Mix Playback Switch",
2851 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2857 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2858 hda_nid_t nid, int pin_type,
2862 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2863 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2865 case 0x11: /* port-A - DAC 04 */
2866 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2868 case 0x14: /* port-B - DAC 06 */
2869 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2871 case 0x15: /* port-C - DAC 05 */
2872 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2874 case 0x17: /* port-E - DAC 0a */
2875 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2877 case 0x13: /* mono - DAC 04 */
2878 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2883 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2885 struct ad198x_spec *spec = codec->spec;
2888 for (i = 0; i < spec->autocfg.line_outs; i++) {
2889 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2890 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2894 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2896 struct ad198x_spec *spec = codec->spec;
2899 pin = spec->autocfg.speaker_pins[0];
2900 if (pin) /* connect to front */
2901 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2902 pin = spec->autocfg.hp_pins[0];
2903 if (pin) /* connect to front */
2904 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2907 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2909 struct ad198x_spec *spec = codec->spec;
2912 for (i = 0; i < AUTO_PIN_LAST; i++) {
2913 hda_nid_t nid = spec->autocfg.input_pins[i];
2917 case 0x15: /* port-C */
2918 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2920 case 0x17: /* port-E */
2921 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2924 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2925 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2926 if (nid != AD1988_PIN_CD_NID)
2927 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2929 idx = ad1988_pin_idx(nid);
2930 if (ad1988_boost_nids[idx])
2931 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2932 AC_VERB_SET_AMP_GAIN_MUTE,
2937 /* parse the BIOS configuration and set up the alc_spec */
2938 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2939 static int ad1988_parse_auto_config(struct hda_codec *codec)
2941 struct ad198x_spec *spec = codec->spec;
2944 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2946 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2948 if (! spec->autocfg.line_outs)
2949 return 0; /* can't find valid BIOS pin config */
2950 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2951 (err = ad1988_auto_create_extra_out(codec,
2952 spec->autocfg.speaker_pins[0],
2954 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2955 "Headphone")) < 0 ||
2956 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2959 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2961 if (spec->autocfg.dig_outs)
2962 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2963 if (spec->autocfg.dig_in_pin)
2964 spec->dig_in_nid = AD1988_SPDIF_IN;
2966 if (spec->kctls.list)
2967 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2969 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2971 spec->input_mux = &spec->private_imux;
2976 /* init callback for auto-configuration model -- overriding the default init */
2977 static int ad1988_auto_init(struct hda_codec *codec)
2980 ad1988_auto_init_multi_out(codec);
2981 ad1988_auto_init_extra_out(codec);
2982 ad1988_auto_init_analog_input(codec);
2990 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2991 [AD1988_6STACK] = "6stack",
2992 [AD1988_6STACK_DIG] = "6stack-dig",
2993 [AD1988_3STACK] = "3stack",
2994 [AD1988_3STACK_DIG] = "3stack-dig",
2995 [AD1988_LAPTOP] = "laptop",
2996 [AD1988_LAPTOP_DIG] = "laptop-dig",
2997 [AD1988_AUTO] = "auto",
3000 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
3001 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3002 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3003 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3004 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3008 static int patch_ad1988(struct hda_codec *codec)
3010 struct ad198x_spec *spec;
3011 int err, board_config;
3013 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3020 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3022 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3023 ad1988_models, ad1988_cfg_tbl);
3024 if (board_config < 0) {
3025 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3027 board_config = AD1988_AUTO;
3030 if (board_config == AD1988_AUTO) {
3031 /* automatic parse from the BIOS config */
3032 err = ad1988_parse_auto_config(codec);
3037 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3038 board_config = AD1988_6STACK;
3042 err = snd_hda_attach_beep_device(codec, 0x10);
3047 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3049 switch (board_config) {
3051 case AD1988_6STACK_DIG:
3052 spec->multiout.max_channels = 8;
3053 spec->multiout.num_dacs = 4;
3055 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3057 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3058 spec->input_mux = &ad1988_6stack_capture_source;
3059 spec->num_mixers = 2;
3061 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3063 spec->mixers[0] = ad1988_6stack_mixers1;
3064 spec->mixers[1] = ad1988_6stack_mixers2;
3065 spec->num_init_verbs = 1;
3066 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3067 if (board_config == AD1988_6STACK_DIG) {
3068 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3069 spec->dig_in_nid = AD1988_SPDIF_IN;
3073 case AD1988_3STACK_DIG:
3074 spec->multiout.max_channels = 6;
3075 spec->multiout.num_dacs = 3;
3077 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3079 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3080 spec->input_mux = &ad1988_6stack_capture_source;
3081 spec->channel_mode = ad1988_3stack_modes;
3082 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3083 spec->num_mixers = 2;
3085 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3087 spec->mixers[0] = ad1988_3stack_mixers1;
3088 spec->mixers[1] = ad1988_3stack_mixers2;
3089 spec->num_init_verbs = 1;
3090 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3091 if (board_config == AD1988_3STACK_DIG)
3092 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3095 case AD1988_LAPTOP_DIG:
3096 spec->multiout.max_channels = 2;
3097 spec->multiout.num_dacs = 1;
3098 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3099 spec->input_mux = &ad1988_laptop_capture_source;
3100 spec->num_mixers = 1;
3101 spec->mixers[0] = ad1988_laptop_mixers;
3102 spec->inv_eapd = 1; /* inverted EAPD */
3103 spec->num_init_verbs = 1;
3104 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3105 if (board_config == AD1988_LAPTOP_DIG)
3106 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3110 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3111 spec->adc_nids = ad1988_adc_nids;
3112 spec->capsrc_nids = ad1988_capsrc_nids;
3113 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3114 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3115 if (spec->multiout.dig_out_nid) {
3116 if (codec->vendor_id >= 0x11d4989a) {
3117 spec->mixers[spec->num_mixers++] =
3118 ad1989_spdif_out_mixers;
3119 spec->init_verbs[spec->num_init_verbs++] =
3120 ad1989_spdif_init_verbs;
3121 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3123 spec->mixers[spec->num_mixers++] =
3124 ad1988_spdif_out_mixers;
3125 spec->init_verbs[spec->num_init_verbs++] =
3126 ad1988_spdif_init_verbs;
3129 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3130 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3132 codec->patch_ops = ad198x_patch_ops;
3133 switch (board_config) {
3135 codec->patch_ops.init = ad1988_auto_init;
3138 case AD1988_LAPTOP_DIG:
3139 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3142 #ifdef CONFIG_SND_HDA_POWER_SAVE
3143 spec->loopback.amplist = ad1988_loopbacks;
3145 spec->vmaster_nid = 0x04;
3154 * port-B - front line/mic-in
3155 * port-E - aux in/out
3156 * port-F - aux in/out
3157 * port-C - rear line/mic-in
3158 * port-D - rear line/hp-out
3159 * port-A - front line/hp-out
3161 * AD1984 = AD1884 + two digital mic-ins
3164 * For simplicity, we share the single DAC for both HP and line-outs
3165 * right now. The inidividual playbacks could be easily implemented,
3166 * but no build-up framework is given, so far.
3169 static hda_nid_t ad1884_dac_nids[1] = {
3173 static hda_nid_t ad1884_adc_nids[2] = {
3177 static hda_nid_t ad1884_capsrc_nids[2] = {
3181 #define AD1884_SPDIF_OUT 0x02
3183 static struct hda_input_mux ad1884_capture_source = {
3186 { "Front Mic", 0x0 },
3193 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3194 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3195 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3196 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3197 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3198 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3199 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3200 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3201 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3202 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3203 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3204 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3205 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3206 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3207 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3208 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3209 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3210 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3211 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3213 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3214 /* The multiple "Capture Source" controls confuse alsamixer
3215 * So call somewhat different..
3217 /* .name = "Capture Source", */
3218 .name = "Input Source",
3220 .info = ad198x_mux_enum_info,
3221 .get = ad198x_mux_enum_get,
3222 .put = ad198x_mux_enum_put,
3224 /* SPDIF controls */
3225 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3228 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3229 /* identical with ad1983 */
3230 .info = ad1983_spdif_route_info,
3231 .get = ad1983_spdif_route_get,
3232 .put = ad1983_spdif_route_put,
3237 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3238 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3239 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3240 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3242 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3248 * initialization verbs
3250 static struct hda_verb ad1884_init_verbs[] = {
3251 /* DACs; mute as default */
3252 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3253 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3254 /* Port-A (HP) mixer */
3255 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3256 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3258 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3259 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3260 /* HP selector - select DAC2 */
3261 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3262 /* Port-D (Line-out) mixer */
3263 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3264 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3266 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3267 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3268 /* Mono-out mixer */
3269 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3270 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3272 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3273 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3275 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3276 /* Port-B (front mic) pin */
3277 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3278 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3279 /* Port-C (rear mic) pin */
3280 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3281 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3282 /* Analog mixer; mute as default */
3283 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3284 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3285 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3286 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3287 /* Analog Mix output amp */
3288 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3289 /* SPDIF output selector */
3290 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3291 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3295 #ifdef CONFIG_SND_HDA_POWER_SAVE
3296 static struct hda_amp_list ad1884_loopbacks[] = {
3297 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3298 { 0x20, HDA_INPUT, 1 }, /* Mic */
3299 { 0x20, HDA_INPUT, 2 }, /* CD */
3300 { 0x20, HDA_INPUT, 4 }, /* Docking */
3305 static const char *ad1884_slave_vols[] = {
3306 "PCM Playback Volume",
3307 "Mic Playback Volume",
3308 "Mono Playback Volume",
3309 "Front Mic Playback Volume",
3310 "Mic Playback Volume",
3311 "CD Playback Volume",
3312 "Internal Mic Playback Volume",
3313 "Docking Mic Playback Volume",
3314 /* "Beep Playback Volume", */
3315 "IEC958 Playback Volume",
3319 static int patch_ad1884(struct hda_codec *codec)
3321 struct ad198x_spec *spec;
3324 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3330 err = snd_hda_attach_beep_device(codec, 0x10);
3335 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3337 spec->multiout.max_channels = 2;
3338 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3339 spec->multiout.dac_nids = ad1884_dac_nids;
3340 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3341 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3342 spec->adc_nids = ad1884_adc_nids;
3343 spec->capsrc_nids = ad1884_capsrc_nids;
3344 spec->input_mux = &ad1884_capture_source;
3345 spec->num_mixers = 1;
3346 spec->mixers[0] = ad1884_base_mixers;
3347 spec->num_init_verbs = 1;
3348 spec->init_verbs[0] = ad1884_init_verbs;
3349 spec->spdif_route = 0;
3350 #ifdef CONFIG_SND_HDA_POWER_SAVE
3351 spec->loopback.amplist = ad1884_loopbacks;
3353 spec->vmaster_nid = 0x04;
3354 /* we need to cover all playback volumes */
3355 spec->slave_vols = ad1884_slave_vols;
3357 codec->patch_ops = ad198x_patch_ops;
3363 * Lenovo Thinkpad T61/X61
3365 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3369 { "Internal Mic", 0x1 },
3371 { "Docking-Station", 0x4 },
3377 * Dell Precision T3400
3379 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3382 { "Front Mic", 0x0 },
3389 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3390 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3391 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3392 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3393 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3394 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3395 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3396 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3397 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3398 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3399 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3400 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3401 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3402 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3403 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3404 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3405 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3406 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3409 /* The multiple "Capture Source" controls confuse alsamixer
3410 * So call somewhat different..
3412 /* .name = "Capture Source", */
3413 .name = "Input Source",
3415 .info = ad198x_mux_enum_info,
3416 .get = ad198x_mux_enum_get,
3417 .put = ad198x_mux_enum_put,
3419 /* SPDIF controls */
3420 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3423 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3424 /* identical with ad1983 */
3425 .info = ad1983_spdif_route_info,
3426 .get = ad1983_spdif_route_get,
3427 .put = ad1983_spdif_route_put,
3432 /* additional verbs */
3433 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3434 /* Port-E (docking station mic) pin */
3435 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3436 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3437 /* docking mic boost */
3438 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3439 /* Analog mixer - docking mic; mute as default */
3440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3441 /* enable EAPD bit */
3442 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3447 * Dell Precision T3400
3449 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3450 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3451 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3452 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3453 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3454 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3455 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3456 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3457 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3458 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3459 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3460 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3461 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3462 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3463 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3464 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3467 /* The multiple "Capture Source" controls confuse alsamixer
3468 * So call somewhat different..
3470 /* .name = "Capture Source", */
3471 .name = "Input Source",
3473 .info = ad198x_mux_enum_info,
3474 .get = ad198x_mux_enum_get,
3475 .put = ad198x_mux_enum_put,
3480 /* Digial MIC ADC NID 0x05 + 0x06 */
3481 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3482 struct hda_codec *codec,
3483 unsigned int stream_tag,
3484 unsigned int format,
3485 struct snd_pcm_substream *substream)
3487 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3488 stream_tag, 0, format);
3492 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3493 struct hda_codec *codec,
3494 struct snd_pcm_substream *substream)
3496 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3500 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3506 .prepare = ad1984_pcm_dmic_prepare,
3507 .cleanup = ad1984_pcm_dmic_cleanup
3511 static int ad1984_build_pcms(struct hda_codec *codec)
3513 struct ad198x_spec *spec = codec->spec;
3514 struct hda_pcm *info;
3517 err = ad198x_build_pcms(codec);
3521 info = spec->pcm_rec + codec->num_pcms;
3523 info->name = "AD1984 Digital Mic";
3524 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3532 AD1984_DELL_DESKTOP,
3536 static const char *ad1984_models[AD1984_MODELS] = {
3537 [AD1984_BASIC] = "basic",
3538 [AD1984_THINKPAD] = "thinkpad",
3539 [AD1984_DELL_DESKTOP] = "dell_desktop",
3542 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3543 /* Lenovo Thinkpad T61/X61 */
3544 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3545 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3549 static int patch_ad1984(struct hda_codec *codec)
3551 struct ad198x_spec *spec;
3552 int board_config, err;
3554 err = patch_ad1884(codec);
3558 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3559 ad1984_models, ad1984_cfg_tbl);
3560 switch (board_config) {
3562 /* additional digital mics */
3563 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3564 codec->patch_ops.build_pcms = ad1984_build_pcms;
3566 case AD1984_THINKPAD:
3567 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3568 spec->input_mux = &ad1984_thinkpad_capture_source;
3569 spec->mixers[0] = ad1984_thinkpad_mixers;
3570 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3572 case AD1984_DELL_DESKTOP:
3573 spec->multiout.dig_out_nid = 0;
3574 spec->input_mux = &ad1984_dell_desktop_capture_source;
3575 spec->mixers[0] = ad1984_dell_desktop_mixers;
3583 * AD1883 / AD1884A / AD1984A / AD1984B
3585 * port-B (0x14) - front mic-in
3586 * port-E (0x1c) - rear mic-in
3587 * port-F (0x16) - CD / ext out
3588 * port-C (0x15) - rear line-in
3589 * port-D (0x12) - rear line-out
3590 * port-A (0x11) - front hp-out
3592 * AD1984A = AD1884A + digital-mic
3593 * AD1883 = equivalent with AD1984A
3594 * AD1984B = AD1984A + extra SPDIF-out
3597 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3600 static hda_nid_t ad1884a_dac_nids[1] = {
3604 #define ad1884a_adc_nids ad1884_adc_nids
3605 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3607 #define AD1884A_SPDIF_OUT 0x02
3609 static struct hda_input_mux ad1884a_capture_source = {
3612 { "Front Mic", 0x0 },
3620 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3621 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3622 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3623 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3624 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3625 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3626 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3627 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3628 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3629 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3630 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3631 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3632 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3633 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3634 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3635 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3636 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3637 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3638 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3639 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3640 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3641 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3642 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3643 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3645 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3646 /* The multiple "Capture Source" controls confuse alsamixer
3647 * So call somewhat different..
3649 /* .name = "Capture Source", */
3650 .name = "Input Source",
3652 .info = ad198x_mux_enum_info,
3653 .get = ad198x_mux_enum_get,
3654 .put = ad198x_mux_enum_put,
3656 /* SPDIF controls */
3657 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3660 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3661 /* identical with ad1983 */
3662 .info = ad1983_spdif_route_info,
3663 .get = ad1983_spdif_route_get,
3664 .put = ad1983_spdif_route_put,
3670 * initialization verbs
3672 static struct hda_verb ad1884a_init_verbs[] = {
3673 /* DACs; unmute as default */
3674 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3675 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3676 /* Port-A (HP) mixer - route only from analog mixer */
3677 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3678 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3680 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3681 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3682 /* Port-D (Line-out) mixer - route only from analog mixer */
3683 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3684 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3686 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3687 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3688 /* Mono-out mixer - route only from analog mixer */
3689 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3690 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3692 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3693 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3694 /* Port-B (front mic) pin */
3695 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3696 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3697 /* Port-C (rear line-in) pin */
3698 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3699 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3700 /* Port-E (rear mic) pin */
3701 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3702 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3703 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3704 /* Port-F (CD) pin */
3705 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3706 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3707 /* Analog mixer; mute as default */
3708 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3709 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3710 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3711 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3712 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3713 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3714 /* Analog Mix output amp */
3715 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3716 /* capture sources */
3717 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3718 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3719 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3720 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3721 /* SPDIF output amp */
3722 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3726 #ifdef CONFIG_SND_HDA_POWER_SAVE
3727 static struct hda_amp_list ad1884a_loopbacks[] = {
3728 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3729 { 0x20, HDA_INPUT, 1 }, /* Mic */
3730 { 0x20, HDA_INPUT, 2 }, /* CD */
3731 { 0x20, HDA_INPUT, 4 }, /* Docking */
3739 * Port A: Headphone jack
3741 * Port C: Internal MIC
3742 * Port D: Dock Line Out (if enabled)
3743 * Port E: Dock Line In (if enabled)
3744 * Port F: Internal speakers
3747 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3748 struct snd_ctl_elem_value *ucontrol)
3750 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3751 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3752 int mute = (!ucontrol->value.integer.value[0] &&
3753 !ucontrol->value.integer.value[1]);
3754 /* toggle GPIO1 according to the mute state */
3755 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3760 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3761 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3763 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3764 .name = "Master Playback Switch",
3765 .subdevice = HDA_SUBDEV_AMP_FLAG,
3766 .info = snd_hda_mixer_amp_switch_info,
3767 .get = snd_hda_mixer_amp_switch_get,
3768 .put = ad1884a_mobile_master_sw_put,
3769 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3771 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3772 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3773 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3774 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3775 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3776 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3777 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3778 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3779 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3780 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3781 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3782 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3783 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3784 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3788 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3789 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3790 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3792 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3793 .name = "Master Playback Switch",
3794 .subdevice = HDA_SUBDEV_AMP_FLAG,
3795 .info = snd_hda_mixer_amp_switch_info,
3796 .get = snd_hda_mixer_amp_switch_get,
3797 .put = ad1884a_mobile_master_sw_put,
3798 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3800 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3801 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3802 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3803 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3804 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3805 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3809 /* mute internal speaker if HP is plugged */
3810 static void ad1884a_hp_automute(struct hda_codec *codec)
3812 unsigned int present;
3814 present = snd_hda_jack_detect(codec, 0x11);
3815 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3816 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3817 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3818 present ? 0x00 : 0x02);
3821 /* switch to external mic if plugged */
3822 static void ad1884a_hp_automic(struct hda_codec *codec)
3824 unsigned int present;
3826 present = snd_hda_jack_detect(codec, 0x14);
3827 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3831 #define AD1884A_HP_EVENT 0x37
3832 #define AD1884A_MIC_EVENT 0x36
3834 /* unsolicited event for HP jack sensing */
3835 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3837 switch (res >> 26) {
3838 case AD1884A_HP_EVENT:
3839 ad1884a_hp_automute(codec);
3841 case AD1884A_MIC_EVENT:
3842 ad1884a_hp_automic(codec);
3847 /* initialize jack-sensing, too */
3848 static int ad1884a_hp_init(struct hda_codec *codec)
3851 ad1884a_hp_automute(codec);
3852 ad1884a_hp_automic(codec);
3856 /* mute internal speaker if HP or docking HP is plugged */
3857 static void ad1884a_laptop_automute(struct hda_codec *codec)
3859 unsigned int present;
3861 present = snd_hda_jack_detect(codec, 0x11);
3863 present = snd_hda_jack_detect(codec, 0x12);
3864 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3865 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3866 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3867 present ? 0x00 : 0x02);
3870 /* switch to external mic if plugged */
3871 static void ad1884a_laptop_automic(struct hda_codec *codec)
3875 if (snd_hda_jack_detect(codec, 0x14))
3877 else if (snd_hda_jack_detect(codec, 0x1c))
3881 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3884 /* unsolicited event for HP jack sensing */
3885 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3888 switch (res >> 26) {
3889 case AD1884A_HP_EVENT:
3890 ad1884a_laptop_automute(codec);
3892 case AD1884A_MIC_EVENT:
3893 ad1884a_laptop_automic(codec);
3898 /* initialize jack-sensing, too */
3899 static int ad1884a_laptop_init(struct hda_codec *codec)
3902 ad1884a_laptop_automute(codec);
3903 ad1884a_laptop_automic(codec);
3907 /* additional verbs for laptop model */
3908 static struct hda_verb ad1884a_laptop_verbs[] = {
3909 /* Port-A (HP) pin - always unmuted */
3910 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3911 /* Port-F (int speaker) mixer - route only from analog mixer */
3912 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3913 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3914 /* Port-F (int speaker) pin */
3915 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3916 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3917 /* required for compaq 6530s/6531s speaker output */
3918 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3919 /* Port-C pin - internal mic-in */
3920 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3921 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3922 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3923 /* Port-D (docking line-out) pin - default unmuted */
3924 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3926 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3927 /* unsolicited event for pin-sense */
3928 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3929 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3930 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3931 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3932 /* allow to touch GPIO1 (for mute control) */
3933 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3934 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3935 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3939 static struct hda_verb ad1884a_mobile_verbs[] = {
3940 /* DACs; unmute as default */
3941 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3942 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3943 /* Port-A (HP) mixer - route only from analog mixer */
3944 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3945 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3947 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3948 /* Port-A (HP) pin - always unmuted */
3949 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3950 /* Port-B (mic jack) pin */
3951 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3952 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3953 /* Port-C (int mic) pin */
3954 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3955 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3956 /* Port-F (int speaker) mixer - route only from analog mixer */
3957 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3958 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3960 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3961 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3962 /* Analog mixer; mute as default */
3963 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3964 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3965 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3966 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3967 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3968 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3969 /* Analog Mix output amp */
3970 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3971 /* capture sources */
3972 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
3973 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3974 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3975 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3976 /* unsolicited event for pin-sense */
3977 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3978 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3979 /* allow to touch GPIO1 (for mute control) */
3980 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3981 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3982 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3991 * 0x17 - built-in mic
3994 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3996 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3998 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4000 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4001 /* unsolicited event for pin-sense */
4002 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4003 /* internal mic - dmic */
4004 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4005 /* set magic COEFs for dmic */
4006 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4007 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4011 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4012 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4013 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4014 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4015 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4016 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4017 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4018 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4019 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4020 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4021 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4023 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4024 .name = "Capture Source",
4025 .info = ad198x_mux_enum_info,
4026 .get = ad198x_mux_enum_get,
4027 .put = ad198x_mux_enum_put,
4032 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4036 { "Internal Mic", 0x5 },
4041 /* mute internal speaker if HP is plugged */
4042 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4044 unsigned int present;
4046 present = snd_hda_jack_detect(codec, 0x11);
4047 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4048 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4051 /* unsolicited event for HP jack sensing */
4052 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4055 if ((res >> 26) != AD1884A_HP_EVENT)
4057 ad1984a_thinkpad_automute(codec);
4060 /* initialize jack-sensing, too */
4061 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4064 ad1984a_thinkpad_automute(codec);
4070 * port-A (0x11) - front hp-out
4071 * port-B (0x14) - unused
4072 * port-C (0x15) - unused
4073 * port-D (0x12) - rear line out
4074 * port-E (0x1c) - front mic-in
4075 * port-F (0x16) - Internal speakers
4076 * digital-mic (0x17) - Internal mic
4079 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4080 /* DACs; unmute as default */
4081 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4082 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4083 /* Port-A (HP) mixer - route only from analog mixer */
4084 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4085 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4087 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4088 /* Port-A (HP) pin - always unmuted */
4089 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4090 /* Port-E (int speaker) mixer - route only from analog mixer */
4091 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4093 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4094 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4095 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4096 /* Port-F (int speaker) mixer - route only from analog mixer */
4097 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4098 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4100 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4101 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4102 /* Analog mixer; mute as default */
4103 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4104 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4105 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4106 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4107 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4108 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4109 /* Analog Mix output amp */
4110 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4111 /* capture sources */
4112 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4113 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4114 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4115 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4116 /* unsolicited event for pin-sense */
4117 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4118 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4119 /* allow to touch GPIO1 (for mute control) */
4120 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4121 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4122 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4123 /* internal mic - dmic */
4124 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4125 /* set magic COEFs for dmic */
4126 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4127 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4131 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4132 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4133 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4135 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4136 .subdevice = HDA_SUBDEV_AMP_FLAG,
4137 .name = "Master Playback Switch",
4138 .info = snd_hda_mixer_amp_switch_info,
4139 .get = snd_hda_mixer_amp_switch_get,
4140 .put = ad1884a_mobile_master_sw_put,
4141 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4143 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4144 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4145 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4146 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4147 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4148 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4152 /* switch to external mic if plugged */
4153 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4155 if (snd_hda_jack_detect(codec, 0x1c))
4156 snd_hda_codec_write(codec, 0x0c, 0,
4157 AC_VERB_SET_CONNECT_SEL, 0x4);
4159 snd_hda_codec_write(codec, 0x0c, 0,
4160 AC_VERB_SET_CONNECT_SEL, 0x5);
4164 /* unsolicited event for HP jack sensing */
4165 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4168 switch (res >> 26) {
4169 case AD1884A_HP_EVENT:
4170 ad1884a_hp_automute(codec);
4172 case AD1884A_MIC_EVENT:
4173 ad1984a_touchsmart_automic(codec);
4178 /* initialize jack-sensing, too */
4179 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4182 ad1884a_hp_automute(codec);
4183 ad1984a_touchsmart_automic(codec);
4200 static const char *ad1884a_models[AD1884A_MODELS] = {
4201 [AD1884A_DESKTOP] = "desktop",
4202 [AD1884A_LAPTOP] = "laptop",
4203 [AD1884A_MOBILE] = "mobile",
4204 [AD1884A_THINKPAD] = "thinkpad",
4205 [AD1984A_TOUCHSMART] = "touchsmart",
4208 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4209 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4210 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4211 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4212 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4213 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4214 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4215 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4216 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4217 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4218 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4222 static int patch_ad1884a(struct hda_codec *codec)
4224 struct ad198x_spec *spec;
4225 int err, board_config;
4227 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4233 err = snd_hda_attach_beep_device(codec, 0x10);
4238 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4240 spec->multiout.max_channels = 2;
4241 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4242 spec->multiout.dac_nids = ad1884a_dac_nids;
4243 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4244 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4245 spec->adc_nids = ad1884a_adc_nids;
4246 spec->capsrc_nids = ad1884a_capsrc_nids;
4247 spec->input_mux = &ad1884a_capture_source;
4248 spec->num_mixers = 1;
4249 spec->mixers[0] = ad1884a_base_mixers;
4250 spec->num_init_verbs = 1;
4251 spec->init_verbs[0] = ad1884a_init_verbs;
4252 spec->spdif_route = 0;
4253 #ifdef CONFIG_SND_HDA_POWER_SAVE
4254 spec->loopback.amplist = ad1884a_loopbacks;
4256 codec->patch_ops = ad198x_patch_ops;
4258 /* override some parameters */
4259 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4262 switch (board_config) {
4263 case AD1884A_LAPTOP:
4264 spec->mixers[0] = ad1884a_laptop_mixers;
4265 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4266 spec->multiout.dig_out_nid = 0;
4267 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4268 codec->patch_ops.init = ad1884a_laptop_init;
4269 /* set the upper-limit for mixer amp to 0dB for avoiding the
4270 * possible damage by overloading
4272 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4273 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4274 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4275 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4276 (1 << AC_AMPCAP_MUTE_SHIFT));
4278 case AD1884A_MOBILE:
4279 spec->mixers[0] = ad1884a_mobile_mixers;
4280 spec->init_verbs[0] = ad1884a_mobile_verbs;
4281 spec->multiout.dig_out_nid = 0;
4282 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4283 codec->patch_ops.init = ad1884a_hp_init;
4284 /* set the upper-limit for mixer amp to 0dB for avoiding the
4285 * possible damage by overloading
4287 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4288 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4289 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4290 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4291 (1 << AC_AMPCAP_MUTE_SHIFT));
4293 case AD1884A_THINKPAD:
4294 spec->mixers[0] = ad1984a_thinkpad_mixers;
4295 spec->init_verbs[spec->num_init_verbs++] =
4296 ad1984a_thinkpad_verbs;
4297 spec->multiout.dig_out_nid = 0;
4298 spec->input_mux = &ad1984a_thinkpad_capture_source;
4299 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4300 codec->patch_ops.init = ad1984a_thinkpad_init;
4302 case AD1984A_TOUCHSMART:
4303 spec->mixers[0] = ad1984a_touchsmart_mixers;
4304 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4305 spec->multiout.dig_out_nid = 0;
4306 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4307 codec->patch_ops.init = ad1984a_touchsmart_init;
4308 /* set the upper-limit for mixer amp to 0dB for avoiding the
4309 * possible damage by overloading
4311 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4312 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4313 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4314 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4315 (1 << AC_AMPCAP_MUTE_SHIFT));
4326 * port-A - front hp-out
4327 * port-B - front mic-in
4328 * port-C - rear line-in, shared surr-out (3stack)
4329 * port-D - rear line-out
4330 * port-E - rear mic-in, shared clfe-out (3stack)
4331 * port-F - rear surr-out (6stack)
4332 * port-G - rear clfe-out (6stack)
4335 static hda_nid_t ad1882_dac_nids[3] = {
4339 static hda_nid_t ad1882_adc_nids[2] = {
4343 static hda_nid_t ad1882_capsrc_nids[2] = {
4347 #define AD1882_SPDIF_OUT 0x02
4349 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4350 static struct hda_input_mux ad1882_capture_source = {
4353 { "Front Mic", 0x1 },
4361 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4362 static struct hda_input_mux ad1882a_capture_source = {
4365 { "Front Mic", 0x1 },
4368 { "Digital Mic", 0x06 },
4373 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4374 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4375 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4376 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4377 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4378 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4379 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4380 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4381 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4383 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4384 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4385 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4386 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4387 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4388 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4389 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4392 /* The multiple "Capture Source" controls confuse alsamixer
4393 * So call somewhat different..
4395 /* .name = "Capture Source", */
4396 .name = "Input Source",
4398 .info = ad198x_mux_enum_info,
4399 .get = ad198x_mux_enum_get,
4400 .put = ad198x_mux_enum_put,
4402 /* SPDIF controls */
4403 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4405 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4406 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4407 /* identical with ad1983 */
4408 .info = ad1983_spdif_route_info,
4409 .get = ad1983_spdif_route_get,
4410 .put = ad1983_spdif_route_put,
4415 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4416 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4417 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4418 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4419 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4420 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4421 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4422 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4423 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4427 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4428 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4429 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4430 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4431 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4432 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4433 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4434 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4435 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4436 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4440 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4441 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4442 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4443 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4445 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4446 .name = "Channel Mode",
4447 .info = ad198x_ch_mode_info,
4448 .get = ad198x_ch_mode_get,
4449 .put = ad198x_ch_mode_put,
4454 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4455 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4456 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4457 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4461 static struct hda_verb ad1882_ch2_init[] = {
4462 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4463 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4464 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4465 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4466 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4467 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4471 static struct hda_verb ad1882_ch4_init[] = {
4472 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4473 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4474 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4475 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4476 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4477 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4481 static struct hda_verb ad1882_ch6_init[] = {
4482 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4483 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4484 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4485 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4486 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4487 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4491 static struct hda_channel_mode ad1882_modes[3] = {
4492 { 2, ad1882_ch2_init },
4493 { 4, ad1882_ch4_init },
4494 { 6, ad1882_ch6_init },
4498 * initialization verbs
4500 static struct hda_verb ad1882_init_verbs[] = {
4501 /* DACs; mute as default */
4502 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4503 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4504 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4505 /* Port-A (HP) mixer */
4506 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4507 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4509 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4510 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4511 /* HP selector - select DAC2 */
4512 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4513 /* Port-D (Line-out) mixer */
4514 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4515 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4517 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4518 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4519 /* Mono-out mixer */
4520 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4521 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4523 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4524 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4525 /* Port-B (front mic) pin */
4526 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4527 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4528 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4529 /* Port-C (line-in) pin */
4530 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4531 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4532 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4533 /* Port-C mixer - mute as input */
4534 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4535 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4536 /* Port-E (mic-in) pin */
4537 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4538 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4539 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4540 /* Port-E mixer - mute as input */
4541 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4542 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4543 /* Port-F (surround) */
4544 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4545 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4547 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4548 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4549 /* Analog mixer; mute as default */
4550 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4551 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4552 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4553 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4554 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4555 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4556 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4557 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4558 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4559 /* Analog Mix output amp */
4560 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4561 /* SPDIF output selector */
4562 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4563 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4564 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4568 #ifdef CONFIG_SND_HDA_POWER_SAVE
4569 static struct hda_amp_list ad1882_loopbacks[] = {
4570 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4571 { 0x20, HDA_INPUT, 1 }, /* Mic */
4572 { 0x20, HDA_INPUT, 4 }, /* Line */
4573 { 0x20, HDA_INPUT, 6 }, /* CD */
4585 static const char *ad1882_models[AD1986A_MODELS] = {
4586 [AD1882_3STACK] = "3stack",
4587 [AD1882_6STACK] = "6stack",
4591 static int patch_ad1882(struct hda_codec *codec)
4593 struct ad198x_spec *spec;
4594 int err, board_config;
4596 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4602 err = snd_hda_attach_beep_device(codec, 0x10);
4607 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4609 spec->multiout.max_channels = 6;
4610 spec->multiout.num_dacs = 3;
4611 spec->multiout.dac_nids = ad1882_dac_nids;
4612 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4613 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4614 spec->adc_nids = ad1882_adc_nids;
4615 spec->capsrc_nids = ad1882_capsrc_nids;
4616 if (codec->vendor_id == 0x11d41882)
4617 spec->input_mux = &ad1882_capture_source;
4619 spec->input_mux = &ad1882a_capture_source;
4620 spec->num_mixers = 2;
4621 spec->mixers[0] = ad1882_base_mixers;
4622 if (codec->vendor_id == 0x11d41882)
4623 spec->mixers[1] = ad1882_loopback_mixers;
4625 spec->mixers[1] = ad1882a_loopback_mixers;
4626 spec->num_init_verbs = 1;
4627 spec->init_verbs[0] = ad1882_init_verbs;
4628 spec->spdif_route = 0;
4629 #ifdef CONFIG_SND_HDA_POWER_SAVE
4630 spec->loopback.amplist = ad1882_loopbacks;
4632 spec->vmaster_nid = 0x04;
4634 codec->patch_ops = ad198x_patch_ops;
4636 /* override some parameters */
4637 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4638 ad1882_models, NULL);
4639 switch (board_config) {
4642 spec->num_mixers = 3;
4643 spec->mixers[2] = ad1882_3stack_mixers;
4644 spec->channel_mode = ad1882_modes;
4645 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4646 spec->need_dac_fix = 1;
4647 spec->multiout.max_channels = 2;
4648 spec->multiout.num_dacs = 1;
4651 spec->num_mixers = 3;
4652 spec->mixers[2] = ad1882_6stack_mixers;
4662 static struct hda_codec_preset snd_hda_preset_analog[] = {
4663 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4664 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4665 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4666 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4667 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4668 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4669 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4670 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4671 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4672 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4673 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4674 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4675 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4676 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4677 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4681 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4683 MODULE_LICENSE("GPL");
4684 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4686 static struct hda_codec_preset_list analog_list = {
4687 .preset = snd_hda_preset_analog,
4688 .owner = THIS_MODULE,
4691 static int __init patch_analog_init(void)
4693 return snd_hda_add_codec_preset(&analog_list);
4696 static void __exit patch_analog_exit(void)
4698 snd_hda_delete_codec_preset(&analog_list);
4701 module_init(patch_analog_init)
4702 module_exit(patch_analog_exit)