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;
77 #ifdef CONFIG_SND_HDA_POWER_SAVE
78 struct hda_loopback_check loopback;
80 /* for virtual master */
81 hda_nid_t vmaster_nid;
82 const char **slave_vols;
83 const char **slave_sws;
87 * input MUX handling (common part)
89 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
91 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
92 struct ad198x_spec *spec = codec->spec;
94 return snd_hda_input_mux_info(spec->input_mux, uinfo);
97 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
99 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
100 struct ad198x_spec *spec = codec->spec;
101 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
103 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
107 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
109 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
110 struct ad198x_spec *spec = codec->spec;
111 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
113 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
114 spec->capsrc_nids[adc_idx],
115 &spec->cur_mux[adc_idx]);
119 * initialization (common callbacks)
121 static int ad198x_init(struct hda_codec *codec)
123 struct ad198x_spec *spec = codec->spec;
126 for (i = 0; i < spec->num_init_verbs; i++)
127 snd_hda_sequence_write(codec, spec->init_verbs[i]);
131 static const char *ad_slave_vols[] = {
132 "Front Playback Volume",
133 "Surround Playback Volume",
134 "Center Playback Volume",
135 "LFE Playback Volume",
136 "Side Playback Volume",
137 "Headphone Playback Volume",
138 "Mono Playback Volume",
139 "Speaker Playback Volume",
140 "IEC958 Playback Volume",
144 static const char *ad_slave_sws[] = {
145 "Front Playback Switch",
146 "Surround Playback Switch",
147 "Center Playback Switch",
148 "LFE Playback Switch",
149 "Side Playback Switch",
150 "Headphone Playback Switch",
151 "Mono Playback Switch",
152 "Speaker Playback Switch",
153 "IEC958 Playback Switch",
157 static void ad198x_free_kctls(struct hda_codec *codec);
159 #ifdef CONFIG_SND_HDA_INPUT_BEEP
160 /* additional beep mixers; the actual parameters are overwritten at build */
161 static struct snd_kcontrol_new ad_beep_mixer[] = {
162 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
163 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
167 #define set_beep_amp(spec, nid, idx, dir) \
168 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
170 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
173 static int ad198x_build_controls(struct hda_codec *codec)
175 struct ad198x_spec *spec = codec->spec;
179 for (i = 0; i < spec->num_mixers; i++) {
180 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
184 if (spec->multiout.dig_out_nid) {
185 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
188 err = snd_hda_create_spdif_share_sw(codec,
192 spec->multiout.share_spdif = 1;
194 if (spec->dig_in_nid) {
195 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
200 /* create beep controls if needed */
201 #ifdef CONFIG_SND_HDA_INPUT_BEEP
202 if (spec->beep_amp) {
203 struct snd_kcontrol_new *knew;
204 for (knew = ad_beep_mixer; knew->name; knew++) {
205 struct snd_kcontrol *kctl;
206 kctl = snd_ctl_new1(knew, codec);
209 kctl->private_value = spec->beep_amp;
210 err = snd_hda_ctl_add(codec,
211 get_amp_nid_(spec->beep_amp),
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 */
244 #ifdef CONFIG_SND_HDA_POWER_SAVE
245 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
247 struct ad198x_spec *spec = codec->spec;
248 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
253 * Analog playback callbacks
255 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
256 struct hda_codec *codec,
257 struct snd_pcm_substream *substream)
259 struct ad198x_spec *spec = codec->spec;
260 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
264 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
265 struct hda_codec *codec,
266 unsigned int stream_tag,
268 struct snd_pcm_substream *substream)
270 struct ad198x_spec *spec = codec->spec;
271 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
275 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
276 struct hda_codec *codec,
277 struct snd_pcm_substream *substream)
279 struct ad198x_spec *spec = codec->spec;
280 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
286 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
287 struct hda_codec *codec,
288 struct snd_pcm_substream *substream)
290 struct ad198x_spec *spec = codec->spec;
291 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
294 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
295 struct hda_codec *codec,
296 struct snd_pcm_substream *substream)
298 struct ad198x_spec *spec = codec->spec;
299 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
302 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
303 struct hda_codec *codec,
304 unsigned int stream_tag,
306 struct snd_pcm_substream *substream)
308 struct ad198x_spec *spec = codec->spec;
309 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
313 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
314 struct hda_codec *codec,
315 struct snd_pcm_substream *substream)
317 struct ad198x_spec *spec = codec->spec;
318 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
324 static int ad198x_capture_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 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
332 stream_tag, 0, format);
336 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
337 struct hda_codec *codec,
338 struct snd_pcm_substream *substream)
340 struct ad198x_spec *spec = codec->spec;
341 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
348 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
351 .channels_max = 6, /* changed later */
352 .nid = 0, /* fill later */
354 .open = ad198x_playback_pcm_open,
355 .prepare = ad198x_playback_pcm_prepare,
356 .cleanup = ad198x_playback_pcm_cleanup
360 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
364 .nid = 0, /* fill later */
366 .prepare = ad198x_capture_pcm_prepare,
367 .cleanup = ad198x_capture_pcm_cleanup
371 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
375 .nid = 0, /* fill later */
377 .open = ad198x_dig_playback_pcm_open,
378 .close = ad198x_dig_playback_pcm_close,
379 .prepare = ad198x_dig_playback_pcm_prepare,
380 .cleanup = ad198x_dig_playback_pcm_cleanup
384 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
388 /* NID is set in alc_build_pcms */
391 static int ad198x_build_pcms(struct hda_codec *codec)
393 struct ad198x_spec *spec = codec->spec;
394 struct hda_pcm *info = spec->pcm_rec;
397 codec->pcm_info = info;
399 info->name = "AD198x Analog";
400 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
401 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
402 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
403 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
404 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
405 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
407 if (spec->multiout.dig_out_nid) {
410 info->name = "AD198x Digital";
411 info->pcm_type = HDA_PCM_TYPE_SPDIF;
412 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
413 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
414 if (spec->dig_in_nid) {
415 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
416 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
423 static void ad198x_free_kctls(struct hda_codec *codec)
425 struct ad198x_spec *spec = codec->spec;
427 if (spec->kctls.list) {
428 struct snd_kcontrol_new *kctl = spec->kctls.list;
430 for (i = 0; i < spec->kctls.used; i++)
433 snd_array_free(&spec->kctls);
436 static void ad198x_free(struct hda_codec *codec)
438 struct ad198x_spec *spec = codec->spec;
443 ad198x_free_kctls(codec);
445 snd_hda_detach_beep_device(codec);
448 static struct hda_codec_ops ad198x_patch_ops = {
449 .build_controls = ad198x_build_controls,
450 .build_pcms = ad198x_build_pcms,
453 #ifdef CONFIG_SND_HDA_POWER_SAVE
454 .check_power_status = ad198x_check_power_status,
461 * the private value = nid | (invert << 8)
463 #define ad198x_eapd_info snd_ctl_boolean_mono_info
465 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
466 struct snd_ctl_elem_value *ucontrol)
468 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
469 struct ad198x_spec *spec = codec->spec;
470 int invert = (kcontrol->private_value >> 8) & 1;
472 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
474 ucontrol->value.integer.value[0] = spec->cur_eapd;
478 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
479 struct snd_ctl_elem_value *ucontrol)
481 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
482 struct ad198x_spec *spec = codec->spec;
483 int invert = (kcontrol->private_value >> 8) & 1;
484 hda_nid_t nid = kcontrol->private_value & 0xff;
486 eapd = !!ucontrol->value.integer.value[0];
489 if (eapd == spec->cur_eapd)
491 spec->cur_eapd = eapd;
492 snd_hda_codec_write_cache(codec, nid,
493 0, AC_VERB_SET_EAPD_BTLENABLE,
498 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
499 struct snd_ctl_elem_info *uinfo);
500 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_value *ucontrol);
502 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
503 struct snd_ctl_elem_value *ucontrol);
510 #define AD1986A_SPDIF_OUT 0x02
511 #define AD1986A_FRONT_DAC 0x03
512 #define AD1986A_SURR_DAC 0x04
513 #define AD1986A_CLFE_DAC 0x05
514 #define AD1986A_ADC 0x06
516 static hda_nid_t ad1986a_dac_nids[3] = {
517 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
519 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
520 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
522 static struct hda_input_mux ad1986a_capture_source = {
536 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
537 .ops = &snd_hda_bind_vol,
539 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
540 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
541 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
546 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
547 .ops = &snd_hda_bind_sw,
549 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
550 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
551 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
559 static struct snd_kcontrol_new ad1986a_mixers[] = {
561 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
563 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
564 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
565 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
566 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
567 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
568 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
569 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
570 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
571 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
572 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
573 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
574 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
575 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
576 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
577 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
578 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
579 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
580 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
581 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
582 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
583 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
584 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
585 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
586 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
587 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
589 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
590 .name = "Capture Source",
591 .info = ad198x_mux_enum_info,
592 .get = ad198x_mux_enum_get,
593 .put = ad198x_mux_enum_put,
595 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
599 /* additional mixers for 3stack mode */
600 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
603 .name = "Channel Mode",
604 .info = ad198x_ch_mode_info,
605 .get = ad198x_ch_mode_get,
606 .put = ad198x_ch_mode_put,
611 /* laptop model - 2ch only */
612 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
614 /* master controls both pins 0x1a and 0x1b */
615 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
616 .ops = &snd_hda_bind_vol,
618 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
619 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
624 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
625 .ops = &snd_hda_bind_sw,
627 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
628 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
633 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
634 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
635 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
636 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
637 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
638 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
639 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
640 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
641 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
642 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
643 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
644 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
645 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
646 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
648 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
649 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
650 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
651 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
653 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
654 .name = "Capture Source",
655 .info = ad198x_mux_enum_info,
656 .get = ad198x_mux_enum_get,
657 .put = ad198x_mux_enum_put,
662 /* laptop-eapd model - 2ch only */
664 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
668 { "Internal Mic", 0x4 },
673 static struct hda_input_mux ad1986a_automic_capture_source = {
681 static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
682 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
683 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
687 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
688 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
689 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
690 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
691 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
692 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
693 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
694 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
696 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
697 .name = "Capture Source",
698 .info = ad198x_mux_enum_info,
699 .get = ad198x_mux_enum_get,
700 .put = ad198x_mux_enum_put,
703 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
704 .name = "External Amplifier",
705 .info = ad198x_eapd_info,
706 .get = ad198x_eapd_get,
707 .put = ad198x_eapd_put,
708 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
713 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
714 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
715 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
719 /* re-connect the mic boost input according to the jack sensing */
720 static void ad1986a_automic(struct hda_codec *codec)
722 unsigned int present;
723 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
724 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
725 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
726 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
729 #define AD1986A_MIC_EVENT 0x36
731 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
734 if ((res >> 26) != AD1986A_MIC_EVENT)
736 ad1986a_automic(codec);
739 static int ad1986a_automic_init(struct hda_codec *codec)
742 ad1986a_automic(codec);
746 /* laptop-automute - 2ch only */
748 static void ad1986a_update_hp(struct hda_codec *codec)
750 struct ad198x_spec *spec = codec->spec;
753 if (spec->jack_present)
754 mute = HDA_AMP_MUTE; /* mute internal speaker */
756 /* unmute internal speaker if necessary */
757 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
758 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
762 static void ad1986a_hp_automute(struct hda_codec *codec)
764 struct ad198x_spec *spec = codec->spec;
765 unsigned int present;
767 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
768 spec->jack_present = !!(present & 0x80000000);
769 if (spec->inv_jack_detect)
770 spec->jack_present = !spec->jack_present;
771 ad1986a_update_hp(codec);
774 #define AD1986A_HP_EVENT 0x37
776 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
778 if ((res >> 26) != AD1986A_HP_EVENT)
780 ad1986a_hp_automute(codec);
783 static int ad1986a_hp_init(struct hda_codec *codec)
786 ad1986a_hp_automute(codec);
790 /* bind hp and internal speaker mute (with plug check) */
791 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
792 struct snd_ctl_elem_value *ucontrol)
794 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
795 long *valp = ucontrol->value.integer.value;
798 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
800 valp[0] ? 0 : HDA_AMP_MUTE);
801 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
803 valp[1] ? 0 : HDA_AMP_MUTE);
805 ad1986a_update_hp(codec);
809 static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
810 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
813 .name = "Master Playback Switch",
814 .info = snd_hda_mixer_amp_switch_info,
815 .get = snd_hda_mixer_amp_switch_get,
816 .put = ad1986a_hp_master_sw_put,
817 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
824 * initialization verbs
826 static struct hda_verb ad1986a_init_verbs[] = {
827 /* Front, Surround, CLFE DAC; mute as default */
828 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
829 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
830 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
832 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
833 /* HP, Line-Out, Surround, CLFE selectors */
834 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
835 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
836 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
837 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
839 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
840 /* Mic selector: Mic 1/2 pin */
841 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
842 /* Line-in selector: Line-in */
843 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
845 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
846 /* Record selector: mic */
847 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
848 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
849 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
850 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
851 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
852 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
853 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
855 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
856 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
857 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
858 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
859 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
860 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
861 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
863 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
864 /* Front, Surround, CLFE Pins */
865 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
866 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
867 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
869 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
871 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
872 /* Line, Aux, CD, Beep-In Pin */
873 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
874 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
875 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
876 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
877 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
881 static struct hda_verb ad1986a_ch2_init[] = {
882 /* Surround out -> Line In */
883 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
884 /* Line-in selectors */
885 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
887 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
888 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
889 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
893 static struct hda_verb ad1986a_ch4_init[] = {
894 /* Surround out -> Surround */
895 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
896 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
898 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
899 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
903 static struct hda_verb ad1986a_ch6_init[] = {
904 /* Surround out -> Surround out */
905 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
906 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
908 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
909 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
913 static struct hda_channel_mode ad1986a_modes[3] = {
914 { 2, ad1986a_ch2_init },
915 { 4, ad1986a_ch4_init },
916 { 6, ad1986a_ch6_init },
919 /* eapd initialization */
920 static struct hda_verb ad1986a_eapd_init_verbs[] = {
921 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
925 static struct hda_verb ad1986a_automic_verbs[] = {
926 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
927 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
928 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
929 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
930 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
934 /* Ultra initialization */
935 static struct hda_verb ad1986a_ultra_init[] = {
936 /* eapd initialization */
937 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
939 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
940 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
941 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
945 /* pin sensing on HP jack */
946 static struct hda_verb ad1986a_hp_init_verbs[] = {
947 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
951 static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
955 case AD1986A_HP_EVENT:
956 ad1986a_hp_automute(codec);
958 case AD1986A_MIC_EVENT:
959 ad1986a_automic(codec);
964 static int ad1986a_samsung_p50_init(struct hda_codec *codec)
967 ad1986a_hp_automute(codec);
968 ad1986a_automic(codec);
979 AD1986A_LAPTOP_AUTOMUTE,
986 static const char *ad1986a_models[AD1986A_MODELS] = {
987 [AD1986A_6STACK] = "6stack",
988 [AD1986A_3STACK] = "3stack",
989 [AD1986A_LAPTOP] = "laptop",
990 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
991 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
992 [AD1986A_ULTRA] = "ultra",
993 [AD1986A_SAMSUNG] = "samsung",
994 [AD1986A_SAMSUNG_P50] = "samsung-p50",
997 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
998 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
999 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1000 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1001 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1002 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1003 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1004 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1005 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1006 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1007 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1008 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1009 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1010 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1011 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1012 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1013 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1014 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
1015 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1016 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1017 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1018 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1019 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1020 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1021 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1022 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1023 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1024 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1028 #ifdef CONFIG_SND_HDA_POWER_SAVE
1029 static struct hda_amp_list ad1986a_loopbacks[] = {
1030 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1031 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1032 { 0x15, HDA_OUTPUT, 0 }, /* CD */
1033 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1034 { 0x17, HDA_OUTPUT, 0 }, /* Line */
1039 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1041 unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1042 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1045 static int patch_ad1986a(struct hda_codec *codec)
1047 struct ad198x_spec *spec;
1048 int err, board_config;
1050 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1056 err = snd_hda_attach_beep_device(codec, 0x19);
1061 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1063 spec->multiout.max_channels = 6;
1064 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1065 spec->multiout.dac_nids = ad1986a_dac_nids;
1066 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1067 spec->num_adc_nids = 1;
1068 spec->adc_nids = ad1986a_adc_nids;
1069 spec->capsrc_nids = ad1986a_capsrc_nids;
1070 spec->input_mux = &ad1986a_capture_source;
1071 spec->num_mixers = 1;
1072 spec->mixers[0] = ad1986a_mixers;
1073 spec->num_init_verbs = 1;
1074 spec->init_verbs[0] = ad1986a_init_verbs;
1075 #ifdef CONFIG_SND_HDA_POWER_SAVE
1076 spec->loopback.amplist = ad1986a_loopbacks;
1078 spec->vmaster_nid = 0x1b;
1080 codec->patch_ops = ad198x_patch_ops;
1082 /* override some parameters */
1083 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1086 switch (board_config) {
1087 case AD1986A_3STACK:
1088 spec->num_mixers = 2;
1089 spec->mixers[1] = ad1986a_3st_mixers;
1090 spec->num_init_verbs = 2;
1091 spec->init_verbs[1] = ad1986a_ch2_init;
1092 spec->channel_mode = ad1986a_modes;
1093 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1094 spec->need_dac_fix = 1;
1095 spec->multiout.max_channels = 2;
1096 spec->multiout.num_dacs = 1;
1098 case AD1986A_LAPTOP:
1099 spec->mixers[0] = ad1986a_laptop_mixers;
1100 spec->multiout.max_channels = 2;
1101 spec->multiout.num_dacs = 1;
1102 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1104 case AD1986A_LAPTOP_EAPD:
1105 spec->num_mixers = 3;
1106 spec->mixers[0] = ad1986a_laptop_master_mixers;
1107 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1108 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1109 spec->num_init_verbs = 2;
1110 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1111 spec->multiout.max_channels = 2;
1112 spec->multiout.num_dacs = 1;
1113 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1114 if (!is_jack_available(codec, 0x25))
1115 spec->multiout.dig_out_nid = 0;
1116 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1118 case AD1986A_SAMSUNG:
1119 spec->num_mixers = 2;
1120 spec->mixers[0] = ad1986a_laptop_master_mixers;
1121 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1122 spec->num_init_verbs = 3;
1123 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1124 spec->init_verbs[2] = ad1986a_automic_verbs;
1125 spec->multiout.max_channels = 2;
1126 spec->multiout.num_dacs = 1;
1127 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1128 if (!is_jack_available(codec, 0x25))
1129 spec->multiout.dig_out_nid = 0;
1130 spec->input_mux = &ad1986a_automic_capture_source;
1131 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1132 codec->patch_ops.init = ad1986a_automic_init;
1134 case AD1986A_SAMSUNG_P50:
1135 spec->num_mixers = 2;
1136 spec->mixers[0] = ad1986a_automute_master_mixers;
1137 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1138 spec->num_init_verbs = 4;
1139 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1140 spec->init_verbs[2] = ad1986a_automic_verbs;
1141 spec->init_verbs[3] = ad1986a_hp_init_verbs;
1142 spec->multiout.max_channels = 2;
1143 spec->multiout.num_dacs = 1;
1144 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1145 if (!is_jack_available(codec, 0x25))
1146 spec->multiout.dig_out_nid = 0;
1147 spec->input_mux = &ad1986a_automic_capture_source;
1148 codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1149 codec->patch_ops.init = ad1986a_samsung_p50_init;
1151 case AD1986A_LAPTOP_AUTOMUTE:
1152 spec->num_mixers = 3;
1153 spec->mixers[0] = ad1986a_automute_master_mixers;
1154 spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1155 spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1156 spec->num_init_verbs = 3;
1157 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1158 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1159 spec->multiout.max_channels = 2;
1160 spec->multiout.num_dacs = 1;
1161 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1162 if (!is_jack_available(codec, 0x25))
1163 spec->multiout.dig_out_nid = 0;
1164 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1165 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1166 codec->patch_ops.init = ad1986a_hp_init;
1167 /* Lenovo N100 seems to report the reversed bit
1168 * for HP jack-sensing
1170 spec->inv_jack_detect = 1;
1173 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1174 spec->num_init_verbs = 2;
1175 spec->init_verbs[1] = ad1986a_ultra_init;
1176 spec->multiout.max_channels = 2;
1177 spec->multiout.num_dacs = 1;
1178 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1179 spec->multiout.dig_out_nid = 0;
1183 /* AD1986A has a hardware problem that it can't share a stream
1184 * with multiple output pins. The copy of front to surrounds
1185 * causes noisy or silent outputs at a certain timing, e.g.
1186 * changing the volume.
1187 * So, let's disable the shared stream.
1189 spec->multiout.no_share_stream = 1;
1198 #define AD1983_SPDIF_OUT 0x02
1199 #define AD1983_DAC 0x03
1200 #define AD1983_ADC 0x04
1202 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1203 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1204 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1206 static struct hda_input_mux ad1983_capture_source = {
1212 { "Mix Mono", 0x3 },
1217 * SPDIF playback route
1219 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1221 static char *texts[] = { "PCM", "ADC" };
1223 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1225 uinfo->value.enumerated.items = 2;
1226 if (uinfo->value.enumerated.item > 1)
1227 uinfo->value.enumerated.item = 1;
1228 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1232 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1234 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1235 struct ad198x_spec *spec = codec->spec;
1237 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1241 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1243 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1244 struct ad198x_spec *spec = codec->spec;
1246 if (ucontrol->value.enumerated.item[0] > 1)
1248 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1249 spec->spdif_route = ucontrol->value.enumerated.item[0];
1250 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1251 AC_VERB_SET_CONNECT_SEL,
1258 static struct snd_kcontrol_new ad1983_mixers[] = {
1259 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1260 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1261 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1262 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1263 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1264 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1265 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1266 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1267 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1268 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1269 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1270 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1271 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1272 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1273 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276 .name = "Capture Source",
1277 .info = ad198x_mux_enum_info,
1278 .get = ad198x_mux_enum_get,
1279 .put = ad198x_mux_enum_put,
1282 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1283 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1284 .info = ad1983_spdif_route_info,
1285 .get = ad1983_spdif_route_get,
1286 .put = ad1983_spdif_route_put,
1291 static struct hda_verb ad1983_init_verbs[] = {
1292 /* Front, HP, Mono; mute as default */
1293 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1294 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1295 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1296 /* Beep, PCM, Mic, Line-In: mute */
1297 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1298 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1299 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1300 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1301 /* Front, HP selectors; from Mix */
1302 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1303 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1304 /* Mono selector; from Mix */
1305 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1306 /* Mic selector; Mic */
1307 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1308 /* Line-in selector: Line-in */
1309 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1310 /* Mic boost: 0dB */
1311 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1312 /* Record selector: mic */
1313 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1314 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1315 /* SPDIF route: PCM */
1316 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1318 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1320 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1322 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1324 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1326 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1330 #ifdef CONFIG_SND_HDA_POWER_SAVE
1331 static struct hda_amp_list ad1983_loopbacks[] = {
1332 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1333 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1338 static int patch_ad1983(struct hda_codec *codec)
1340 struct ad198x_spec *spec;
1343 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1349 err = snd_hda_attach_beep_device(codec, 0x10);
1354 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1356 spec->multiout.max_channels = 2;
1357 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1358 spec->multiout.dac_nids = ad1983_dac_nids;
1359 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1360 spec->num_adc_nids = 1;
1361 spec->adc_nids = ad1983_adc_nids;
1362 spec->capsrc_nids = ad1983_capsrc_nids;
1363 spec->input_mux = &ad1983_capture_source;
1364 spec->num_mixers = 1;
1365 spec->mixers[0] = ad1983_mixers;
1366 spec->num_init_verbs = 1;
1367 spec->init_verbs[0] = ad1983_init_verbs;
1368 spec->spdif_route = 0;
1369 #ifdef CONFIG_SND_HDA_POWER_SAVE
1370 spec->loopback.amplist = ad1983_loopbacks;
1372 spec->vmaster_nid = 0x05;
1374 codec->patch_ops = ad198x_patch_ops;
1381 * AD1981 HD specific
1384 #define AD1981_SPDIF_OUT 0x02
1385 #define AD1981_DAC 0x03
1386 #define AD1981_ADC 0x04
1388 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1389 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1390 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1392 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1393 static struct hda_input_mux ad1981_capture_source = {
1396 { "Front Mic", 0x0 },
1399 { "Mix Mono", 0x3 },
1406 static struct snd_kcontrol_new ad1981_mixers[] = {
1407 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1408 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1409 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1410 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1411 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1412 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1413 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1414 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1415 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1416 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1417 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1418 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1419 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1420 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1421 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1422 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1423 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1424 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1425 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1426 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1427 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1428 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1431 .name = "Capture Source",
1432 .info = ad198x_mux_enum_info,
1433 .get = ad198x_mux_enum_get,
1434 .put = ad198x_mux_enum_put,
1436 /* identical with AD1983 */
1438 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1440 .info = ad1983_spdif_route_info,
1441 .get = ad1983_spdif_route_get,
1442 .put = ad1983_spdif_route_put,
1447 static struct hda_verb ad1981_init_verbs[] = {
1448 /* Front, HP, Mono; mute as default */
1449 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1450 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1451 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1452 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1453 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1454 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1455 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1456 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1457 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1458 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1459 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1460 /* Front, HP selectors; from Mix */
1461 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1462 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1463 /* Mono selector; from Mix */
1464 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1465 /* Mic Mixer; select Front Mic */
1466 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1467 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1468 /* Mic boost: 0dB */
1469 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1470 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1471 /* Record selector: Front mic */
1472 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1473 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1474 /* SPDIF route: PCM */
1475 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1477 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1479 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1481 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1482 /* Front & Rear Mic Pins */
1483 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1484 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1486 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1488 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1489 /* Line-Out as Input: disabled */
1490 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1494 #ifdef CONFIG_SND_HDA_POWER_SAVE
1495 static struct hda_amp_list ad1981_loopbacks[] = {
1496 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1497 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1498 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1499 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1500 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1506 * Patch for HP nx6320
1508 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1509 * speaker output enabled _and_ mute-LED off.
1512 #define AD1981_HP_EVENT 0x37
1513 #define AD1981_MIC_EVENT 0x38
1515 static struct hda_verb ad1981_hp_init_verbs[] = {
1516 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1517 /* pin sensing on HP and Mic jacks */
1518 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1519 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1523 /* turn on/off EAPD (+ mute HP) as a master switch */
1524 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1525 struct snd_ctl_elem_value *ucontrol)
1527 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1528 struct ad198x_spec *spec = codec->spec;
1530 if (! ad198x_eapd_put(kcontrol, ucontrol))
1532 /* change speaker pin appropriately */
1533 snd_hda_codec_write(codec, 0x05, 0,
1534 AC_VERB_SET_PIN_WIDGET_CONTROL,
1535 spec->cur_eapd ? PIN_OUT : 0);
1536 /* toggle HP mute appropriately */
1537 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1539 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1543 /* bind volumes of both NID 0x05 and 0x06 */
1544 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1545 .ops = &snd_hda_bind_vol,
1547 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1548 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1553 /* mute internal speaker if HP is plugged */
1554 static void ad1981_hp_automute(struct hda_codec *codec)
1556 unsigned int present;
1558 present = snd_hda_codec_read(codec, 0x06, 0,
1559 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1560 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1561 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1564 /* toggle input of built-in and mic jack appropriately */
1565 static void ad1981_hp_automic(struct hda_codec *codec)
1567 static struct hda_verb mic_jack_on[] = {
1568 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1569 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1572 static struct hda_verb mic_jack_off[] = {
1573 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1574 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1577 unsigned int present;
1579 present = snd_hda_codec_read(codec, 0x08, 0,
1580 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1582 snd_hda_sequence_write(codec, mic_jack_on);
1584 snd_hda_sequence_write(codec, mic_jack_off);
1587 /* unsolicited event for HP jack sensing */
1588 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1593 case AD1981_HP_EVENT:
1594 ad1981_hp_automute(codec);
1596 case AD1981_MIC_EVENT:
1597 ad1981_hp_automic(codec);
1602 static struct hda_input_mux ad1981_hp_capture_source = {
1606 { "Docking-Station", 0x1 },
1611 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1612 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1614 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1615 .name = "Master Playback Switch",
1616 .info = ad198x_eapd_info,
1617 .get = ad198x_eapd_get,
1618 .put = ad1981_hp_master_sw_put,
1619 .private_value = 0x05,
1621 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1622 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1624 /* FIXME: analog mic/line loopback doesn't work with my tests...
1625 * (although recording is OK)
1627 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1628 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1629 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1630 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1631 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1632 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1633 /* FIXME: does this laptop have analog CD connection? */
1634 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1635 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1637 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1638 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1639 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1640 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1643 .name = "Capture Source",
1644 .info = ad198x_mux_enum_info,
1645 .get = ad198x_mux_enum_get,
1646 .put = ad198x_mux_enum_put,
1651 /* initialize jack-sensing, too */
1652 static int ad1981_hp_init(struct hda_codec *codec)
1655 ad1981_hp_automute(codec);
1656 ad1981_hp_automic(codec);
1660 /* configuration for Toshiba Laptops */
1661 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1662 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1663 /* pin sensing on HP and Mic jacks */
1664 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1665 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1669 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1670 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1671 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1675 /* configuration for Lenovo Thinkpad T60 */
1676 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1677 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1678 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1679 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1680 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1681 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1682 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1683 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1684 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1685 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1686 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1687 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1689 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1690 .name = "Capture Source",
1691 .info = ad198x_mux_enum_info,
1692 .get = ad198x_mux_enum_get,
1693 .put = ad198x_mux_enum_put,
1695 /* identical with AD1983 */
1697 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1698 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1699 .info = ad1983_spdif_route_info,
1700 .get = ad1983_spdif_route_get,
1701 .put = ad1983_spdif_route_put,
1706 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1724 static const char *ad1981_models[AD1981_MODELS] = {
1726 [AD1981_THINKPAD] = "thinkpad",
1727 [AD1981_BASIC] = "basic",
1728 [AD1981_TOSHIBA] = "toshiba"
1731 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1732 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1733 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1735 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1736 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1737 /* Lenovo Thinkpad T60/X60/Z6xx */
1738 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1739 /* HP nx6320 (reversed SSID, H/W bug) */
1740 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1744 static int patch_ad1981(struct hda_codec *codec)
1746 struct ad198x_spec *spec;
1747 int err, board_config;
1749 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1755 err = snd_hda_attach_beep_device(codec, 0x10);
1760 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1762 spec->multiout.max_channels = 2;
1763 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1764 spec->multiout.dac_nids = ad1981_dac_nids;
1765 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1766 spec->num_adc_nids = 1;
1767 spec->adc_nids = ad1981_adc_nids;
1768 spec->capsrc_nids = ad1981_capsrc_nids;
1769 spec->input_mux = &ad1981_capture_source;
1770 spec->num_mixers = 1;
1771 spec->mixers[0] = ad1981_mixers;
1772 spec->num_init_verbs = 1;
1773 spec->init_verbs[0] = ad1981_init_verbs;
1774 spec->spdif_route = 0;
1775 #ifdef CONFIG_SND_HDA_POWER_SAVE
1776 spec->loopback.amplist = ad1981_loopbacks;
1778 spec->vmaster_nid = 0x05;
1780 codec->patch_ops = ad198x_patch_ops;
1782 /* override some parameters */
1783 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1786 switch (board_config) {
1788 spec->mixers[0] = ad1981_hp_mixers;
1789 spec->num_init_verbs = 2;
1790 spec->init_verbs[1] = ad1981_hp_init_verbs;
1791 spec->multiout.dig_out_nid = 0;
1792 spec->input_mux = &ad1981_hp_capture_source;
1794 codec->patch_ops.init = ad1981_hp_init;
1795 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1797 case AD1981_THINKPAD:
1798 spec->mixers[0] = ad1981_thinkpad_mixers;
1799 spec->input_mux = &ad1981_thinkpad_capture_source;
1801 case AD1981_TOSHIBA:
1802 spec->mixers[0] = ad1981_hp_mixers;
1803 spec->mixers[1] = ad1981_toshiba_mixers;
1804 spec->num_init_verbs = 2;
1805 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1806 spec->multiout.dig_out_nid = 0;
1807 spec->input_mux = &ad1981_hp_capture_source;
1808 codec->patch_ops.init = ad1981_hp_init;
1809 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1819 * Output pins and routes
1821 * Pin Mix Sel DAC (*)
1822 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1823 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1824 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1825 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1826 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1827 * port-F 0x16 (mute) <- 0x2a <- 06
1828 * port-G 0x24 (mute) <- 0x27 <- 05
1829 * port-H 0x25 (mute) <- 0x28 <- 0a
1830 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1832 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1833 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1835 * Input pins and routes
1837 * pin boost mix input # / adc input #
1838 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1839 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1840 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1841 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1842 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1843 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1844 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1845 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1849 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1850 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1852 * Inputs of Analog Mix (0x20)
1853 * 0:Port-B (front mic)
1854 * 1:Port-C/G/H (line-in)
1856 * 3:Port-D (line-in/2)
1857 * 4:Port-E/G/H (mic-in)
1858 * 5:Port-F (mic2-in)
1864 * 1:Port-B (front mic-in)
1865 * 2:Port-C (line-in)
1866 * 3:Port-F (mic2-in)
1871 * 8:Port-D (line-in/2)
1874 * Proposed pin assignments by the datasheet
1877 * Port-A front headphone
1887 * Port-A front headphone
1889 * C rear line-in/surround
1891 * E rear mic-in/CLFE
1897 * D internal speaker (with EAPD)
1898 * E/F quad mic array
1914 /* reivision id to check workarounds */
1915 #define AD1988A_REV2 0x100200
1917 #define is_rev2(codec) \
1918 ((codec)->vendor_id == 0x11d41988 && \
1919 (codec)->revision_id == AD1988A_REV2)
1925 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1926 0x04, 0x06, 0x05, 0x0a
1929 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1933 /* for AD1988A revision-2, DAC2-4 are swapped */
1934 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1935 0x04, 0x05, 0x0a, 0x06
1938 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1942 static hda_nid_t ad1988_adc_nids[3] = {
1946 static hda_nid_t ad1988_capsrc_nids[3] = {
1950 #define AD1988_SPDIF_OUT 0x02
1951 #define AD1988_SPDIF_OUT_HDMI 0x0b
1952 #define AD1988_SPDIF_IN 0x07
1954 static hda_nid_t ad1989b_slave_dig_outs[] = {
1955 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
1958 static struct hda_input_mux ad1988_6stack_capture_source = {
1961 { "Front Mic", 0x1 }, /* port-B */
1962 { "Line", 0x2 }, /* port-C */
1963 { "Mic", 0x4 }, /* port-E */
1969 static struct hda_input_mux ad1988_laptop_capture_source = {
1972 { "Mic/Line", 0x1 }, /* port-B */
1980 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1981 struct snd_ctl_elem_info *uinfo)
1983 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1984 struct ad198x_spec *spec = codec->spec;
1985 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1986 spec->num_channel_mode);
1989 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1990 struct snd_ctl_elem_value *ucontrol)
1992 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1993 struct ad198x_spec *spec = codec->spec;
1994 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1995 spec->num_channel_mode, spec->multiout.max_channels);
1998 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1999 struct snd_ctl_elem_value *ucontrol)
2001 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2002 struct ad198x_spec *spec = codec->spec;
2003 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2004 spec->num_channel_mode,
2005 &spec->multiout.max_channels);
2006 if (err >= 0 && spec->need_dac_fix)
2007 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2012 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2013 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2014 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2015 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2016 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2017 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2021 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2022 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2023 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2024 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2025 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2026 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2030 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2031 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2032 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2033 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2034 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2035 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2036 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2037 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2039 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2040 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2041 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2042 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2043 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2044 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2045 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2046 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2048 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2049 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2051 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2052 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2058 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2059 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2060 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2061 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2062 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2066 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2067 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2068 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2069 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2070 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2074 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2075 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2076 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2077 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2078 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2079 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2080 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2082 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2083 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2084 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2085 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2086 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2087 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2088 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2089 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2091 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2092 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2094 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2095 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2097 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2098 .name = "Channel Mode",
2099 .info = ad198x_ch_mode_info,
2100 .get = ad198x_ch_mode_get,
2101 .put = ad198x_ch_mode_put,
2108 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2109 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2110 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2111 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2113 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2114 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2115 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2116 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2117 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2118 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2120 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2121 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2123 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2126 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2127 .name = "External Amplifier",
2128 .info = ad198x_eapd_info,
2129 .get = ad198x_eapd_get,
2130 .put = ad198x_eapd_put,
2131 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2138 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2139 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2140 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2141 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2142 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2143 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2144 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2146 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2147 /* The multiple "Capture Source" controls confuse alsamixer
2148 * So call somewhat different..
2150 /* .name = "Capture Source", */
2151 .name = "Input Source",
2153 .info = ad198x_mux_enum_info,
2154 .get = ad198x_mux_enum_get,
2155 .put = ad198x_mux_enum_put,
2160 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2161 struct snd_ctl_elem_info *uinfo)
2163 static char *texts[] = {
2164 "PCM", "ADC1", "ADC2", "ADC3"
2166 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2168 uinfo->value.enumerated.items = 4;
2169 if (uinfo->value.enumerated.item >= 4)
2170 uinfo->value.enumerated.item = 3;
2171 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2175 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2176 struct snd_ctl_elem_value *ucontrol)
2178 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2181 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2184 ucontrol->value.enumerated.item[0] = 0;
2186 sel = snd_hda_codec_read(codec, 0x0b, 0,
2187 AC_VERB_GET_CONNECT_SEL, 0);
2192 ucontrol->value.enumerated.item[0] = sel;
2197 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2198 struct snd_ctl_elem_value *ucontrol)
2200 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2201 unsigned int val, sel;
2204 val = ucontrol->value.enumerated.item[0];
2208 sel = snd_hda_codec_read(codec, 0x1d, 0,
2209 AC_VERB_GET_AMP_GAIN_MUTE,
2211 change = sel & 0x80;
2213 snd_hda_codec_write_cache(codec, 0x1d, 0,
2214 AC_VERB_SET_AMP_GAIN_MUTE,
2216 snd_hda_codec_write_cache(codec, 0x1d, 0,
2217 AC_VERB_SET_AMP_GAIN_MUTE,
2221 sel = snd_hda_codec_read(codec, 0x1d, 0,
2222 AC_VERB_GET_AMP_GAIN_MUTE,
2223 AC_AMP_GET_INPUT | 0x01);
2224 change = sel & 0x80;
2226 snd_hda_codec_write_cache(codec, 0x1d, 0,
2227 AC_VERB_SET_AMP_GAIN_MUTE,
2229 snd_hda_codec_write_cache(codec, 0x1d, 0,
2230 AC_VERB_SET_AMP_GAIN_MUTE,
2233 sel = snd_hda_codec_read(codec, 0x0b, 0,
2234 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2235 change |= sel != val;
2237 snd_hda_codec_write_cache(codec, 0x0b, 0,
2238 AC_VERB_SET_CONNECT_SEL,
2244 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2245 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2247 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2248 .name = "IEC958 Playback Source",
2249 .info = ad1988_spdif_playback_source_info,
2250 .get = ad1988_spdif_playback_source_get,
2251 .put = ad1988_spdif_playback_source_put,
2256 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2257 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2261 static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2262 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2263 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2268 * initialization verbs
2272 * for 6-stack (+dig)
2274 static struct hda_verb ad1988_6stack_init_verbs[] = {
2275 /* Front, Surround, CLFE, side DAC; unmute as default */
2276 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2277 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2278 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2279 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2280 /* Port-A front headphon path */
2281 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2282 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2283 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2284 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2285 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2286 /* Port-D line-out path */
2287 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2288 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2289 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2290 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2291 /* Port-F surround path */
2292 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2293 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2294 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2295 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2296 /* Port-G CLFE path */
2297 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2298 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2299 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2300 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2301 /* Port-H side path */
2302 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2303 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2304 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2305 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2307 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2308 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2309 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2310 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2311 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2312 /* Port-B front mic-in path */
2313 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2314 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2315 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2316 /* Port-C line-in path */
2317 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2318 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2319 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2320 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2321 /* Port-E mic-in path */
2322 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2323 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2324 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2325 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2326 /* Analog CD Input */
2327 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2328 /* Analog Mix output amp */
2329 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2334 static struct hda_verb ad1988_capture_init_verbs[] = {
2335 /* mute analog mix */
2336 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2337 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2338 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2339 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2340 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2341 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2342 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2343 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2344 /* select ADCs - front-mic */
2345 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2346 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2347 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2352 static struct hda_verb ad1988_spdif_init_verbs[] = {
2354 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2355 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2356 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2357 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2359 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2364 /* AD1989 has no ADC -> SPDIF route */
2365 static struct hda_verb ad1989_spdif_init_verbs[] = {
2366 /* SPDIF-1 out pin */
2367 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2368 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2369 /* SPDIF-2/HDMI out pin */
2370 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2371 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2376 * verbs for 3stack (+dig)
2378 static struct hda_verb ad1988_3stack_ch2_init[] = {
2379 /* set port-C to line-in */
2380 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2381 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2382 /* set port-E to mic-in */
2383 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2384 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2388 static struct hda_verb ad1988_3stack_ch6_init[] = {
2389 /* set port-C to surround out */
2390 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2391 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2392 /* set port-E to CLFE out */
2393 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2394 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2398 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2399 { 2, ad1988_3stack_ch2_init },
2400 { 6, ad1988_3stack_ch6_init },
2403 static struct hda_verb ad1988_3stack_init_verbs[] = {
2404 /* Front, Surround, CLFE, side DAC; unmute as default */
2405 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2406 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2407 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2408 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2409 /* Port-A front headphon path */
2410 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2411 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2412 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2413 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2414 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2415 /* Port-D line-out path */
2416 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2417 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2418 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2419 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2421 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2422 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2423 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2424 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2425 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2426 /* Port-B front mic-in path */
2427 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2428 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2429 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2430 /* Port-C line-in/surround path - 6ch mode as default */
2431 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2432 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2433 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2434 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2435 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2436 /* Port-E mic-in/CLFE path - 6ch mode as default */
2437 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2438 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2439 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2440 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2441 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2442 /* mute analog mix */
2443 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2444 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2445 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2446 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2447 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2448 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2449 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2450 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2451 /* select ADCs - front-mic */
2452 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2453 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2454 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2455 /* Analog Mix output amp */
2456 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2461 * verbs for laptop mode (+dig)
2463 static struct hda_verb ad1988_laptop_hp_on[] = {
2464 /* unmute port-A and mute port-D */
2465 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2466 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2469 static struct hda_verb ad1988_laptop_hp_off[] = {
2470 /* mute port-A and unmute port-D */
2471 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2472 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2476 #define AD1988_HP_EVENT 0x01
2478 static struct hda_verb ad1988_laptop_init_verbs[] = {
2479 /* Front, Surround, CLFE, side DAC; unmute as default */
2480 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2481 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2482 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2483 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2484 /* Port-A front headphon path */
2485 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2486 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2487 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2488 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2489 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2490 /* unsolicited event for pin-sense */
2491 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2492 /* Port-D line-out path + EAPD */
2493 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2494 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2495 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2496 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2497 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2499 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2500 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2501 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2502 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2503 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2504 /* Port-B mic-in path */
2505 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2506 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2507 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2508 /* Port-C docking station - try to output */
2509 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2510 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2511 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2512 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2513 /* mute analog mix */
2514 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2515 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2516 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2517 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2518 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2519 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2520 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2521 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2522 /* select ADCs - mic */
2523 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2524 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2525 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2526 /* Analog Mix output amp */
2527 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2531 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2533 if ((res >> 26) != AD1988_HP_EVENT)
2535 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2536 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2538 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2541 #ifdef CONFIG_SND_HDA_POWER_SAVE
2542 static struct hda_amp_list ad1988_loopbacks[] = {
2543 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2544 { 0x20, HDA_INPUT, 1 }, /* Line */
2545 { 0x20, HDA_INPUT, 4 }, /* Mic */
2546 { 0x20, HDA_INPUT, 6 }, /* CD */
2552 * Automatic parse of I/O pins from the BIOS configuration
2560 static struct snd_kcontrol_new ad1988_control_templates[] = {
2561 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2562 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2563 HDA_BIND_MUTE(NULL, 0, 0, 0),
2566 /* add dynamic controls */
2567 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2570 struct snd_kcontrol_new *knew;
2572 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2573 knew = snd_array_new(&spec->kctls);
2576 *knew = ad1988_control_templates[type];
2577 knew->name = kstrdup(name, GFP_KERNEL);
2580 if (get_amp_nid_(val))
2581 knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
2582 knew->private_value = val;
2586 #define AD1988_PIN_CD_NID 0x18
2587 #define AD1988_PIN_BEEP_NID 0x10
2589 static hda_nid_t ad1988_mixer_nids[8] = {
2590 /* A B C D E F G H */
2591 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2594 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2596 static hda_nid_t idx_to_dac[8] = {
2597 /* A B C D E F G H */
2598 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2600 static hda_nid_t idx_to_dac_rev2[8] = {
2601 /* A B C D E F G H */
2602 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2605 return idx_to_dac_rev2[idx];
2607 return idx_to_dac[idx];
2610 static hda_nid_t ad1988_boost_nids[8] = {
2611 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2614 static int ad1988_pin_idx(hda_nid_t nid)
2616 static hda_nid_t ad1988_io_pins[8] = {
2617 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2620 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2621 if (ad1988_io_pins[i] == nid)
2623 return 0; /* should be -1 */
2626 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2628 static int loopback_idx[8] = {
2629 2, 0, 1, 3, 4, 5, 1, 4
2632 case AD1988_PIN_CD_NID:
2635 return loopback_idx[ad1988_pin_idx(nid)];
2639 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2641 static int adc_idx[8] = {
2642 0, 1, 2, 8, 4, 3, 6, 7
2645 case AD1988_PIN_CD_NID:
2648 return adc_idx[ad1988_pin_idx(nid)];
2652 /* fill in the dac_nids table from the parsed pin configuration */
2653 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2654 const struct auto_pin_cfg *cfg)
2656 struct ad198x_spec *spec = codec->spec;
2659 spec->multiout.dac_nids = spec->private_dac_nids;
2661 /* check the pins hardwired to audio widget */
2662 for (i = 0; i < cfg->line_outs; i++) {
2663 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2664 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2666 spec->multiout.num_dacs = cfg->line_outs;
2670 /* add playback controls from the parsed DAC table */
2671 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2672 const struct auto_pin_cfg *cfg)
2675 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2679 for (i = 0; i < cfg->line_outs; i++) {
2680 hda_nid_t dac = spec->multiout.dac_nids[i];
2683 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2686 err = add_control(spec, AD_CTL_WIDGET_VOL,
2687 "Center Playback Volume",
2688 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2691 err = add_control(spec, AD_CTL_WIDGET_VOL,
2692 "LFE Playback Volume",
2693 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2696 err = add_control(spec, AD_CTL_BIND_MUTE,
2697 "Center Playback Switch",
2698 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2701 err = add_control(spec, AD_CTL_BIND_MUTE,
2702 "LFE Playback Switch",
2703 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2707 sprintf(name, "%s Playback Volume", chname[i]);
2708 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2709 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2712 sprintf(name, "%s Playback Switch", chname[i]);
2713 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2714 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2722 /* add playback controls for speaker and HP outputs */
2723 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2726 struct ad198x_spec *spec = codec->spec;
2734 idx = ad1988_pin_idx(pin);
2735 nid = ad1988_idx_to_dac(codec, idx);
2736 /* check whether the corresponding DAC was already taken */
2737 for (i = 0; i < spec->autocfg.line_outs; i++) {
2738 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2739 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2743 if (i >= spec->autocfg.line_outs) {
2744 /* specify the DAC as the extra output */
2745 if (!spec->multiout.hp_nid)
2746 spec->multiout.hp_nid = nid;
2748 spec->multiout.extra_out_nid[0] = nid;
2749 /* control HP volume/switch on the output mixer amp */
2750 sprintf(name, "%s Playback Volume", pfx);
2751 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2752 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2756 nid = ad1988_mixer_nids[idx];
2757 sprintf(name, "%s Playback Switch", pfx);
2758 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2759 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2764 /* create input playback/capture controls for the given pin */
2765 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2766 const char *ctlname, int boost)
2771 sprintf(name, "%s Playback Volume", ctlname);
2772 idx = ad1988_pin_to_loopback_idx(pin);
2773 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2774 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2776 sprintf(name, "%s Playback Switch", ctlname);
2777 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2778 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2782 idx = ad1988_pin_idx(pin);
2783 bnid = ad1988_boost_nids[idx];
2785 sprintf(name, "%s Boost", ctlname);
2786 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2787 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2794 /* create playback/capture controls for input pins */
2795 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2796 const struct auto_pin_cfg *cfg)
2798 struct hda_input_mux *imux = &spec->private_imux;
2801 for (i = 0; i < AUTO_PIN_LAST; i++) {
2802 err = new_analog_input(spec, cfg->input_pins[i],
2803 auto_pin_cfg_labels[i],
2804 i <= AUTO_PIN_FRONT_MIC);
2807 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2808 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2811 imux->items[imux->num_items].label = "Mix";
2812 imux->items[imux->num_items].index = 9;
2815 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2816 "Analog Mix Playback Volume",
2817 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2819 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2820 "Analog Mix Playback Switch",
2821 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2827 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2828 hda_nid_t nid, int pin_type,
2832 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2833 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2835 case 0x11: /* port-A - DAC 04 */
2836 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2838 case 0x14: /* port-B - DAC 06 */
2839 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2841 case 0x15: /* port-C - DAC 05 */
2842 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2844 case 0x17: /* port-E - DAC 0a */
2845 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2847 case 0x13: /* mono - DAC 04 */
2848 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2853 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2855 struct ad198x_spec *spec = codec->spec;
2858 for (i = 0; i < spec->autocfg.line_outs; i++) {
2859 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2860 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2864 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2866 struct ad198x_spec *spec = codec->spec;
2869 pin = spec->autocfg.speaker_pins[0];
2870 if (pin) /* connect to front */
2871 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2872 pin = spec->autocfg.hp_pins[0];
2873 if (pin) /* connect to front */
2874 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2877 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2879 struct ad198x_spec *spec = codec->spec;
2882 for (i = 0; i < AUTO_PIN_LAST; i++) {
2883 hda_nid_t nid = spec->autocfg.input_pins[i];
2887 case 0x15: /* port-C */
2888 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2890 case 0x17: /* port-E */
2891 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2894 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2895 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2896 if (nid != AD1988_PIN_CD_NID)
2897 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2899 idx = ad1988_pin_idx(nid);
2900 if (ad1988_boost_nids[idx])
2901 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2902 AC_VERB_SET_AMP_GAIN_MUTE,
2907 /* parse the BIOS configuration and set up the alc_spec */
2908 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2909 static int ad1988_parse_auto_config(struct hda_codec *codec)
2911 struct ad198x_spec *spec = codec->spec;
2914 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2916 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2918 if (! spec->autocfg.line_outs)
2919 return 0; /* can't find valid BIOS pin config */
2920 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2921 (err = ad1988_auto_create_extra_out(codec,
2922 spec->autocfg.speaker_pins[0],
2924 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2925 "Headphone")) < 0 ||
2926 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2929 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2931 if (spec->autocfg.dig_outs)
2932 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2933 if (spec->autocfg.dig_in_pin)
2934 spec->dig_in_nid = AD1988_SPDIF_IN;
2936 if (spec->kctls.list)
2937 spec->mixers[spec->num_mixers++] = spec->kctls.list;
2939 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2941 spec->input_mux = &spec->private_imux;
2946 /* init callback for auto-configuration model -- overriding the default init */
2947 static int ad1988_auto_init(struct hda_codec *codec)
2950 ad1988_auto_init_multi_out(codec);
2951 ad1988_auto_init_extra_out(codec);
2952 ad1988_auto_init_analog_input(codec);
2960 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2961 [AD1988_6STACK] = "6stack",
2962 [AD1988_6STACK_DIG] = "6stack-dig",
2963 [AD1988_3STACK] = "3stack",
2964 [AD1988_3STACK_DIG] = "3stack-dig",
2965 [AD1988_LAPTOP] = "laptop",
2966 [AD1988_LAPTOP_DIG] = "laptop-dig",
2967 [AD1988_AUTO] = "auto",
2970 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2971 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2972 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2973 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
2974 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
2978 static int patch_ad1988(struct hda_codec *codec)
2980 struct ad198x_spec *spec;
2981 int err, board_config;
2983 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2990 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2992 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2993 ad1988_models, ad1988_cfg_tbl);
2994 if (board_config < 0) {
2995 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
2997 board_config = AD1988_AUTO;
3000 if (board_config == AD1988_AUTO) {
3001 /* automatic parse from the BIOS config */
3002 err = ad1988_parse_auto_config(codec);
3007 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3008 board_config = AD1988_6STACK;
3012 err = snd_hda_attach_beep_device(codec, 0x10);
3017 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3019 switch (board_config) {
3021 case AD1988_6STACK_DIG:
3022 spec->multiout.max_channels = 8;
3023 spec->multiout.num_dacs = 4;
3025 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3027 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3028 spec->input_mux = &ad1988_6stack_capture_source;
3029 spec->num_mixers = 2;
3031 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3033 spec->mixers[0] = ad1988_6stack_mixers1;
3034 spec->mixers[1] = ad1988_6stack_mixers2;
3035 spec->num_init_verbs = 1;
3036 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3037 if (board_config == AD1988_6STACK_DIG) {
3038 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3039 spec->dig_in_nid = AD1988_SPDIF_IN;
3043 case AD1988_3STACK_DIG:
3044 spec->multiout.max_channels = 6;
3045 spec->multiout.num_dacs = 3;
3047 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3049 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3050 spec->input_mux = &ad1988_6stack_capture_source;
3051 spec->channel_mode = ad1988_3stack_modes;
3052 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3053 spec->num_mixers = 2;
3055 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3057 spec->mixers[0] = ad1988_3stack_mixers1;
3058 spec->mixers[1] = ad1988_3stack_mixers2;
3059 spec->num_init_verbs = 1;
3060 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3061 if (board_config == AD1988_3STACK_DIG)
3062 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3065 case AD1988_LAPTOP_DIG:
3066 spec->multiout.max_channels = 2;
3067 spec->multiout.num_dacs = 1;
3068 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3069 spec->input_mux = &ad1988_laptop_capture_source;
3070 spec->num_mixers = 1;
3071 spec->mixers[0] = ad1988_laptop_mixers;
3072 spec->num_init_verbs = 1;
3073 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3074 if (board_config == AD1988_LAPTOP_DIG)
3075 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3079 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3080 spec->adc_nids = ad1988_adc_nids;
3081 spec->capsrc_nids = ad1988_capsrc_nids;
3082 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3083 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3084 if (spec->multiout.dig_out_nid) {
3085 if (codec->vendor_id >= 0x11d4989a) {
3086 spec->mixers[spec->num_mixers++] =
3087 ad1989_spdif_out_mixers;
3088 spec->init_verbs[spec->num_init_verbs++] =
3089 ad1989_spdif_init_verbs;
3090 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3092 spec->mixers[spec->num_mixers++] =
3093 ad1988_spdif_out_mixers;
3094 spec->init_verbs[spec->num_init_verbs++] =
3095 ad1988_spdif_init_verbs;
3098 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
3099 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3101 codec->patch_ops = ad198x_patch_ops;
3102 switch (board_config) {
3104 codec->patch_ops.init = ad1988_auto_init;
3107 case AD1988_LAPTOP_DIG:
3108 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3111 #ifdef CONFIG_SND_HDA_POWER_SAVE
3112 spec->loopback.amplist = ad1988_loopbacks;
3114 spec->vmaster_nid = 0x04;
3123 * port-B - front line/mic-in
3124 * port-E - aux in/out
3125 * port-F - aux in/out
3126 * port-C - rear line/mic-in
3127 * port-D - rear line/hp-out
3128 * port-A - front line/hp-out
3130 * AD1984 = AD1884 + two digital mic-ins
3133 * For simplicity, we share the single DAC for both HP and line-outs
3134 * right now. The inidividual playbacks could be easily implemented,
3135 * but no build-up framework is given, so far.
3138 static hda_nid_t ad1884_dac_nids[1] = {
3142 static hda_nid_t ad1884_adc_nids[2] = {
3146 static hda_nid_t ad1884_capsrc_nids[2] = {
3150 #define AD1884_SPDIF_OUT 0x02
3152 static struct hda_input_mux ad1884_capture_source = {
3155 { "Front Mic", 0x0 },
3162 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3163 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3164 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3165 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3166 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3167 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3168 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3169 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3170 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3171 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3172 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3173 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3174 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3175 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3176 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3177 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3178 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3179 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3180 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3182 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3183 /* The multiple "Capture Source" controls confuse alsamixer
3184 * So call somewhat different..
3186 /* .name = "Capture Source", */
3187 .name = "Input Source",
3189 .info = ad198x_mux_enum_info,
3190 .get = ad198x_mux_enum_get,
3191 .put = ad198x_mux_enum_put,
3193 /* SPDIF controls */
3194 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3196 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3197 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3198 /* identical with ad1983 */
3199 .info = ad1983_spdif_route_info,
3200 .get = ad1983_spdif_route_get,
3201 .put = ad1983_spdif_route_put,
3206 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3207 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3208 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3209 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3211 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3217 * initialization verbs
3219 static struct hda_verb ad1884_init_verbs[] = {
3220 /* DACs; mute as default */
3221 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3222 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3223 /* Port-A (HP) mixer */
3224 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3225 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3227 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3228 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3229 /* HP selector - select DAC2 */
3230 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3231 /* Port-D (Line-out) mixer */
3232 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3233 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3235 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3236 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3237 /* Mono-out mixer */
3238 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3239 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3241 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3242 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3244 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3245 /* Port-B (front mic) pin */
3246 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3247 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3248 /* Port-C (rear mic) pin */
3249 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3250 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3251 /* Analog mixer; mute as default */
3252 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3253 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3254 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3255 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3256 /* Analog Mix output amp */
3257 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3258 /* SPDIF output selector */
3259 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3260 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3264 #ifdef CONFIG_SND_HDA_POWER_SAVE
3265 static struct hda_amp_list ad1884_loopbacks[] = {
3266 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3267 { 0x20, HDA_INPUT, 1 }, /* Mic */
3268 { 0x20, HDA_INPUT, 2 }, /* CD */
3269 { 0x20, HDA_INPUT, 4 }, /* Docking */
3274 static const char *ad1884_slave_vols[] = {
3275 "PCM Playback Volume",
3276 "Mic Playback Volume",
3277 "Mono Playback Volume",
3278 "Front Mic Playback Volume",
3279 "Mic Playback Volume",
3280 "CD Playback Volume",
3281 "Internal Mic Playback Volume",
3282 "Docking Mic Playback Volume",
3283 /* "Beep Playback Volume", */
3284 "IEC958 Playback Volume",
3288 static int patch_ad1884(struct hda_codec *codec)
3290 struct ad198x_spec *spec;
3293 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3299 err = snd_hda_attach_beep_device(codec, 0x10);
3304 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3306 spec->multiout.max_channels = 2;
3307 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3308 spec->multiout.dac_nids = ad1884_dac_nids;
3309 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3310 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3311 spec->adc_nids = ad1884_adc_nids;
3312 spec->capsrc_nids = ad1884_capsrc_nids;
3313 spec->input_mux = &ad1884_capture_source;
3314 spec->num_mixers = 1;
3315 spec->mixers[0] = ad1884_base_mixers;
3316 spec->num_init_verbs = 1;
3317 spec->init_verbs[0] = ad1884_init_verbs;
3318 spec->spdif_route = 0;
3319 #ifdef CONFIG_SND_HDA_POWER_SAVE
3320 spec->loopback.amplist = ad1884_loopbacks;
3322 spec->vmaster_nid = 0x04;
3323 /* we need to cover all playback volumes */
3324 spec->slave_vols = ad1884_slave_vols;
3326 codec->patch_ops = ad198x_patch_ops;
3332 * Lenovo Thinkpad T61/X61
3334 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3338 { "Internal Mic", 0x1 },
3340 { "Docking-Station", 0x4 },
3346 * Dell Precision T3400
3348 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3351 { "Front Mic", 0x0 },
3358 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3359 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3360 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3361 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3362 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3363 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3364 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3365 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3366 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3367 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3368 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3369 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3370 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3371 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3372 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3373 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3374 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3375 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3377 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3378 /* The multiple "Capture Source" controls confuse alsamixer
3379 * So call somewhat different..
3381 /* .name = "Capture Source", */
3382 .name = "Input Source",
3384 .info = ad198x_mux_enum_info,
3385 .get = ad198x_mux_enum_get,
3386 .put = ad198x_mux_enum_put,
3388 /* SPDIF controls */
3389 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3392 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3393 /* identical with ad1983 */
3394 .info = ad1983_spdif_route_info,
3395 .get = ad1983_spdif_route_get,
3396 .put = ad1983_spdif_route_put,
3401 /* additional verbs */
3402 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3403 /* Port-E (docking station mic) pin */
3404 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3405 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3406 /* docking mic boost */
3407 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3408 /* Analog mixer - docking mic; mute as default */
3409 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3410 /* enable EAPD bit */
3411 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3416 * Dell Precision T3400
3418 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3419 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3420 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3421 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3422 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3423 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3424 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3425 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3426 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3427 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3428 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3429 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3430 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3431 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3432 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3433 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3436 /* The multiple "Capture Source" controls confuse alsamixer
3437 * So call somewhat different..
3439 /* .name = "Capture Source", */
3440 .name = "Input Source",
3442 .info = ad198x_mux_enum_info,
3443 .get = ad198x_mux_enum_get,
3444 .put = ad198x_mux_enum_put,
3449 /* Digial MIC ADC NID 0x05 + 0x06 */
3450 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3451 struct hda_codec *codec,
3452 unsigned int stream_tag,
3453 unsigned int format,
3454 struct snd_pcm_substream *substream)
3456 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3457 stream_tag, 0, format);
3461 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3462 struct hda_codec *codec,
3463 struct snd_pcm_substream *substream)
3465 snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3469 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3475 .prepare = ad1984_pcm_dmic_prepare,
3476 .cleanup = ad1984_pcm_dmic_cleanup
3480 static int ad1984_build_pcms(struct hda_codec *codec)
3482 struct ad198x_spec *spec = codec->spec;
3483 struct hda_pcm *info;
3486 err = ad198x_build_pcms(codec);
3490 info = spec->pcm_rec + codec->num_pcms;
3492 info->name = "AD1984 Digital Mic";
3493 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3501 AD1984_DELL_DESKTOP,
3505 static const char *ad1984_models[AD1984_MODELS] = {
3506 [AD1984_BASIC] = "basic",
3507 [AD1984_THINKPAD] = "thinkpad",
3508 [AD1984_DELL_DESKTOP] = "dell_desktop",
3511 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3512 /* Lenovo Thinkpad T61/X61 */
3513 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3514 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3518 static int patch_ad1984(struct hda_codec *codec)
3520 struct ad198x_spec *spec;
3521 int board_config, err;
3523 err = patch_ad1884(codec);
3527 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3528 ad1984_models, ad1984_cfg_tbl);
3529 switch (board_config) {
3531 /* additional digital mics */
3532 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3533 codec->patch_ops.build_pcms = ad1984_build_pcms;
3535 case AD1984_THINKPAD:
3536 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3537 spec->input_mux = &ad1984_thinkpad_capture_source;
3538 spec->mixers[0] = ad1984_thinkpad_mixers;
3539 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3541 case AD1984_DELL_DESKTOP:
3542 spec->multiout.dig_out_nid = 0;
3543 spec->input_mux = &ad1984_dell_desktop_capture_source;
3544 spec->mixers[0] = ad1984_dell_desktop_mixers;
3552 * AD1883 / AD1884A / AD1984A / AD1984B
3554 * port-B (0x14) - front mic-in
3555 * port-E (0x1c) - rear mic-in
3556 * port-F (0x16) - CD / ext out
3557 * port-C (0x15) - rear line-in
3558 * port-D (0x12) - rear line-out
3559 * port-A (0x11) - front hp-out
3561 * AD1984A = AD1884A + digital-mic
3562 * AD1883 = equivalent with AD1984A
3563 * AD1984B = AD1984A + extra SPDIF-out
3566 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3569 static hda_nid_t ad1884a_dac_nids[1] = {
3573 #define ad1884a_adc_nids ad1884_adc_nids
3574 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3576 #define AD1884A_SPDIF_OUT 0x02
3578 static struct hda_input_mux ad1884a_capture_source = {
3581 { "Front Mic", 0x0 },
3589 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3590 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3591 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3592 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3593 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3594 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3595 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3596 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3597 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3598 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3599 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3600 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3601 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3602 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3603 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3604 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3605 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3606 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3607 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3608 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3609 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3610 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3611 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3612 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3614 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3615 /* The multiple "Capture Source" controls confuse alsamixer
3616 * So call somewhat different..
3618 /* .name = "Capture Source", */
3619 .name = "Input Source",
3621 .info = ad198x_mux_enum_info,
3622 .get = ad198x_mux_enum_get,
3623 .put = ad198x_mux_enum_put,
3625 /* SPDIF controls */
3626 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3628 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3629 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3630 /* identical with ad1983 */
3631 .info = ad1983_spdif_route_info,
3632 .get = ad1983_spdif_route_get,
3633 .put = ad1983_spdif_route_put,
3639 * initialization verbs
3641 static struct hda_verb ad1884a_init_verbs[] = {
3642 /* DACs; unmute as default */
3643 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3644 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3645 /* Port-A (HP) mixer - route only from analog mixer */
3646 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3647 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3649 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3650 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3651 /* Port-D (Line-out) mixer - route only from analog mixer */
3652 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3653 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3655 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3656 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3657 /* Mono-out mixer - route only from analog mixer */
3658 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3659 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3661 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3662 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3663 /* Port-B (front mic) pin */
3664 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3665 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3666 /* Port-C (rear line-in) pin */
3667 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3668 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3669 /* Port-E (rear mic) pin */
3670 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3671 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3672 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3673 /* Port-F (CD) pin */
3674 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3675 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3676 /* Analog mixer; mute as default */
3677 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3678 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3679 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3680 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3681 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3682 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3683 /* Analog Mix output amp */
3684 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3685 /* capture sources */
3686 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3687 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3688 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3689 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3690 /* SPDIF output amp */
3691 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3695 #ifdef CONFIG_SND_HDA_POWER_SAVE
3696 static struct hda_amp_list ad1884a_loopbacks[] = {
3697 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3698 { 0x20, HDA_INPUT, 1 }, /* Mic */
3699 { 0x20, HDA_INPUT, 2 }, /* CD */
3700 { 0x20, HDA_INPUT, 4 }, /* Docking */
3708 * Port A: Headphone jack
3710 * Port C: Internal MIC
3711 * Port D: Dock Line Out (if enabled)
3712 * Port E: Dock Line In (if enabled)
3713 * Port F: Internal speakers
3716 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3717 struct snd_ctl_elem_value *ucontrol)
3719 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3720 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3721 int mute = (!ucontrol->value.integer.value[0] &&
3722 !ucontrol->value.integer.value[1]);
3723 /* toggle GPIO1 according to the mute state */
3724 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3729 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3730 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3732 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3733 .name = "Master Playback Switch",
3734 .info = snd_hda_mixer_amp_switch_info,
3735 .get = snd_hda_mixer_amp_switch_get,
3736 .put = ad1884a_mobile_master_sw_put,
3737 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3739 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3740 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3741 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3742 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3743 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3744 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3745 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3746 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3747 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3748 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3749 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3750 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3751 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3752 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3756 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3757 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3758 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3761 .name = "Master Playback Switch",
3762 .info = snd_hda_mixer_amp_switch_info,
3763 .get = snd_hda_mixer_amp_switch_get,
3764 .put = ad1884a_mobile_master_sw_put,
3765 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3767 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3768 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3769 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3770 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3771 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3772 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3776 /* mute internal speaker if HP is plugged */
3777 static void ad1884a_hp_automute(struct hda_codec *codec)
3779 unsigned int present;
3781 present = snd_hda_codec_read(codec, 0x11, 0,
3782 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3783 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3784 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3785 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3786 present ? 0x00 : 0x02);
3789 /* switch to external mic if plugged */
3790 static void ad1884a_hp_automic(struct hda_codec *codec)
3792 unsigned int present;
3794 present = snd_hda_codec_read(codec, 0x14, 0,
3795 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3796 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3800 #define AD1884A_HP_EVENT 0x37
3801 #define AD1884A_MIC_EVENT 0x36
3803 /* unsolicited event for HP jack sensing */
3804 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3806 switch (res >> 26) {
3807 case AD1884A_HP_EVENT:
3808 ad1884a_hp_automute(codec);
3810 case AD1884A_MIC_EVENT:
3811 ad1884a_hp_automic(codec);
3816 /* initialize jack-sensing, too */
3817 static int ad1884a_hp_init(struct hda_codec *codec)
3820 ad1884a_hp_automute(codec);
3821 ad1884a_hp_automic(codec);
3825 /* mute internal speaker if HP or docking HP is plugged */
3826 static void ad1884a_laptop_automute(struct hda_codec *codec)
3828 unsigned int present;
3830 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0);
3831 present &= AC_PINSENSE_PRESENCE;
3833 present = snd_hda_codec_read(codec, 0x12, 0,
3834 AC_VERB_GET_PIN_SENSE, 0);
3835 present &= AC_PINSENSE_PRESENCE;
3837 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3838 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3839 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3840 present ? 0x00 : 0x02);
3843 /* switch to external mic if plugged */
3844 static void ad1884a_laptop_automic(struct hda_codec *codec)
3848 if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) &
3849 AC_PINSENSE_PRESENCE)
3851 else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) &
3852 AC_PINSENSE_PRESENCE)
3856 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3859 /* unsolicited event for HP jack sensing */
3860 static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3863 switch (res >> 26) {
3864 case AD1884A_HP_EVENT:
3865 ad1884a_laptop_automute(codec);
3867 case AD1884A_MIC_EVENT:
3868 ad1884a_laptop_automic(codec);
3873 /* initialize jack-sensing, too */
3874 static int ad1884a_laptop_init(struct hda_codec *codec)
3877 ad1884a_laptop_automute(codec);
3878 ad1884a_laptop_automic(codec);
3882 /* additional verbs for laptop model */
3883 static struct hda_verb ad1884a_laptop_verbs[] = {
3884 /* Port-A (HP) pin - always unmuted */
3885 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3886 /* Port-F (int speaker) mixer - route only from analog mixer */
3887 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3888 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3889 /* Port-F (int speaker) pin */
3890 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3891 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3892 /* required for compaq 6530s/6531s speaker output */
3893 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3894 /* Port-C pin - internal mic-in */
3895 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3896 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3897 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3898 /* Port-D (docking line-out) pin - default unmuted */
3899 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3901 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3902 /* unsolicited event for pin-sense */
3903 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3904 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3905 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3906 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3907 /* allow to touch GPIO1 (for mute control) */
3908 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3909 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3910 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3914 static struct hda_verb ad1884a_mobile_verbs[] = {
3915 /* DACs; unmute as default */
3916 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3917 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3918 /* Port-A (HP) mixer - route only from analog mixer */
3919 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3920 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3922 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3923 /* Port-A (HP) pin - always unmuted */
3924 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3925 /* Port-B (mic jack) pin */
3926 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3927 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3928 /* Port-C (int mic) pin */
3929 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3930 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
3931 /* Port-F (int speaker) mixer - route only from analog mixer */
3932 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3933 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3935 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3936 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3937 /* Analog mixer; mute as default */
3938 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3939 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3940 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3941 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3942 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3943 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3944 /* Analog Mix output amp */
3945 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3946 /* capture sources */
3947 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
3948 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3949 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3950 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3951 /* unsolicited event for pin-sense */
3952 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3953 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
3954 /* allow to touch GPIO1 (for mute control) */
3955 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
3956 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
3957 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
3966 * 0x17 - built-in mic
3969 static struct hda_verb ad1984a_thinkpad_verbs[] = {
3971 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3973 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3975 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3976 /* unsolicited event for pin-sense */
3977 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3978 /* internal mic - dmic */
3979 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3980 /* set magic COEFs for dmic */
3981 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
3982 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
3986 static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
3987 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3988 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3989 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3990 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3991 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3992 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3993 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3994 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
3995 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3996 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3998 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3999 .name = "Capture Source",
4000 .info = ad198x_mux_enum_info,
4001 .get = ad198x_mux_enum_get,
4002 .put = ad198x_mux_enum_put,
4007 static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4011 { "Internal Mic", 0x5 },
4016 /* mute internal speaker if HP is plugged */
4017 static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4019 unsigned int present;
4021 present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
4022 & AC_PINSENSE_PRESENCE;
4023 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4024 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4027 /* unsolicited event for HP jack sensing */
4028 static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4031 if ((res >> 26) != AD1884A_HP_EVENT)
4033 ad1984a_thinkpad_automute(codec);
4036 /* initialize jack-sensing, too */
4037 static int ad1984a_thinkpad_init(struct hda_codec *codec)
4040 ad1984a_thinkpad_automute(codec);
4046 * port-A (0x11) - front hp-out
4047 * port-B (0x14) - unused
4048 * port-C (0x15) - unused
4049 * port-D (0x12) - rear line out
4050 * port-E (0x1c) - front mic-in
4051 * port-F (0x16) - Internal speakers
4052 * digital-mic (0x17) - Internal mic
4055 static struct hda_verb ad1984a_touchsmart_verbs[] = {
4056 /* DACs; unmute as default */
4057 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4058 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4059 /* Port-A (HP) mixer - route only from analog mixer */
4060 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4061 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4063 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4064 /* Port-A (HP) pin - always unmuted */
4065 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4066 /* Port-E (int speaker) mixer - route only from analog mixer */
4067 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4069 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4070 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4071 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4072 /* Port-F (int speaker) mixer - route only from analog mixer */
4073 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4074 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4076 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4077 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4078 /* Analog mixer; mute as default */
4079 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4080 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4081 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4082 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4083 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4084 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4085 /* Analog Mix output amp */
4086 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4087 /* capture sources */
4088 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4089 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4090 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4091 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4092 /* unsolicited event for pin-sense */
4093 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4094 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4095 /* allow to touch GPIO1 (for mute control) */
4096 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4097 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4098 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4099 /* internal mic - dmic */
4100 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4101 /* set magic COEFs for dmic */
4102 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4103 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4107 static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4108 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4109 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4111 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4112 .name = "Master Playback Switch",
4113 .info = snd_hda_mixer_amp_switch_info,
4114 .get = snd_hda_mixer_amp_switch_get,
4115 .put = ad1884a_mobile_master_sw_put,
4116 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4118 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4119 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4120 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4121 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4122 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4123 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4127 /* switch to external mic if plugged */
4128 static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4130 if (snd_hda_codec_read(codec, 0x1c, 0,
4131 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) {
4132 snd_hda_codec_write(codec, 0x0c, 0,
4133 AC_VERB_SET_CONNECT_SEL, 0x4);
4135 snd_hda_codec_write(codec, 0x0c, 0,
4136 AC_VERB_SET_CONNECT_SEL, 0x5);
4141 /* unsolicited event for HP jack sensing */
4142 static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4145 switch (res >> 26) {
4146 case AD1884A_HP_EVENT:
4147 ad1884a_hp_automute(codec);
4149 case AD1884A_MIC_EVENT:
4150 ad1984a_touchsmart_automic(codec);
4155 /* initialize jack-sensing, too */
4156 static int ad1984a_touchsmart_init(struct hda_codec *codec)
4159 ad1884a_hp_automute(codec);
4160 ad1984a_touchsmart_automic(codec);
4177 static const char *ad1884a_models[AD1884A_MODELS] = {
4178 [AD1884A_DESKTOP] = "desktop",
4179 [AD1884A_LAPTOP] = "laptop",
4180 [AD1884A_MOBILE] = "mobile",
4181 [AD1884A_THINKPAD] = "thinkpad",
4182 [AD1984A_TOUCHSMART] = "touchsmart",
4185 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4186 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4187 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4188 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4189 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4190 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4191 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4192 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4193 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4194 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4195 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4199 static int patch_ad1884a(struct hda_codec *codec)
4201 struct ad198x_spec *spec;
4202 int err, board_config;
4204 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4210 err = snd_hda_attach_beep_device(codec, 0x10);
4215 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4217 spec->multiout.max_channels = 2;
4218 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4219 spec->multiout.dac_nids = ad1884a_dac_nids;
4220 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4221 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4222 spec->adc_nids = ad1884a_adc_nids;
4223 spec->capsrc_nids = ad1884a_capsrc_nids;
4224 spec->input_mux = &ad1884a_capture_source;
4225 spec->num_mixers = 1;
4226 spec->mixers[0] = ad1884a_base_mixers;
4227 spec->num_init_verbs = 1;
4228 spec->init_verbs[0] = ad1884a_init_verbs;
4229 spec->spdif_route = 0;
4230 #ifdef CONFIG_SND_HDA_POWER_SAVE
4231 spec->loopback.amplist = ad1884a_loopbacks;
4233 codec->patch_ops = ad198x_patch_ops;
4235 /* override some parameters */
4236 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4239 switch (board_config) {
4240 case AD1884A_LAPTOP:
4241 spec->mixers[0] = ad1884a_laptop_mixers;
4242 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4243 spec->multiout.dig_out_nid = 0;
4244 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4245 codec->patch_ops.init = ad1884a_laptop_init;
4246 /* set the upper-limit for mixer amp to 0dB for avoiding the
4247 * possible damage by overloading
4249 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4250 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4251 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4252 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4253 (1 << AC_AMPCAP_MUTE_SHIFT));
4255 case AD1884A_MOBILE:
4256 spec->mixers[0] = ad1884a_mobile_mixers;
4257 spec->init_verbs[0] = ad1884a_mobile_verbs;
4258 spec->multiout.dig_out_nid = 0;
4259 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4260 codec->patch_ops.init = ad1884a_hp_init;
4261 /* set the upper-limit for mixer amp to 0dB for avoiding the
4262 * possible damage by overloading
4264 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4265 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4266 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4267 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4268 (1 << AC_AMPCAP_MUTE_SHIFT));
4270 case AD1884A_THINKPAD:
4271 spec->mixers[0] = ad1984a_thinkpad_mixers;
4272 spec->init_verbs[spec->num_init_verbs++] =
4273 ad1984a_thinkpad_verbs;
4274 spec->multiout.dig_out_nid = 0;
4275 spec->input_mux = &ad1984a_thinkpad_capture_source;
4276 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4277 codec->patch_ops.init = ad1984a_thinkpad_init;
4279 case AD1984A_TOUCHSMART:
4280 spec->mixers[0] = ad1984a_touchsmart_mixers;
4281 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4282 spec->multiout.dig_out_nid = 0;
4283 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4284 codec->patch_ops.init = ad1984a_touchsmart_init;
4285 /* set the upper-limit for mixer amp to 0dB for avoiding the
4286 * possible damage by overloading
4288 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4289 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4290 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4291 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4292 (1 << AC_AMPCAP_MUTE_SHIFT));
4303 * port-A - front hp-out
4304 * port-B - front mic-in
4305 * port-C - rear line-in, shared surr-out (3stack)
4306 * port-D - rear line-out
4307 * port-E - rear mic-in, shared clfe-out (3stack)
4308 * port-F - rear surr-out (6stack)
4309 * port-G - rear clfe-out (6stack)
4312 static hda_nid_t ad1882_dac_nids[3] = {
4316 static hda_nid_t ad1882_adc_nids[2] = {
4320 static hda_nid_t ad1882_capsrc_nids[2] = {
4324 #define AD1882_SPDIF_OUT 0x02
4326 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4327 static struct hda_input_mux ad1882_capture_source = {
4330 { "Front Mic", 0x1 },
4338 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4339 static struct hda_input_mux ad1882a_capture_source = {
4342 { "Front Mic", 0x1 },
4345 { "Digital Mic", 0x06 },
4350 static struct snd_kcontrol_new ad1882_base_mixers[] = {
4351 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4352 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4353 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4354 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4355 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4356 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4357 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4358 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4360 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4361 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4362 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4363 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4364 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4365 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4366 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4368 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4369 /* The multiple "Capture Source" controls confuse alsamixer
4370 * So call somewhat different..
4372 /* .name = "Capture Source", */
4373 .name = "Input Source",
4375 .info = ad198x_mux_enum_info,
4376 .get = ad198x_mux_enum_get,
4377 .put = ad198x_mux_enum_put,
4379 /* SPDIF controls */
4380 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4382 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4383 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4384 /* identical with ad1983 */
4385 .info = ad1983_spdif_route_info,
4386 .get = ad1983_spdif_route_get,
4387 .put = ad1983_spdif_route_put,
4392 static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4393 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4394 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4395 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4396 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4397 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4398 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4399 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4400 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4404 static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4405 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4406 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4407 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4408 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4409 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4410 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4411 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4412 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4413 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4417 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4418 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4419 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4420 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4423 .name = "Channel Mode",
4424 .info = ad198x_ch_mode_info,
4425 .get = ad198x_ch_mode_get,
4426 .put = ad198x_ch_mode_put,
4431 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4432 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4433 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4434 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4438 static struct hda_verb ad1882_ch2_init[] = {
4439 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4440 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4441 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4442 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4443 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4444 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4448 static struct hda_verb ad1882_ch4_init[] = {
4449 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4450 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4451 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4452 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4453 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4454 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4458 static struct hda_verb ad1882_ch6_init[] = {
4459 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4460 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4461 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4462 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4463 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4464 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4468 static struct hda_channel_mode ad1882_modes[3] = {
4469 { 2, ad1882_ch2_init },
4470 { 4, ad1882_ch4_init },
4471 { 6, ad1882_ch6_init },
4475 * initialization verbs
4477 static struct hda_verb ad1882_init_verbs[] = {
4478 /* DACs; mute as default */
4479 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4480 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4481 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4482 /* Port-A (HP) mixer */
4483 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4484 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4486 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4487 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4488 /* HP selector - select DAC2 */
4489 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4490 /* Port-D (Line-out) mixer */
4491 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4492 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4494 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4495 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4496 /* Mono-out mixer */
4497 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4498 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4500 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4501 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4502 /* Port-B (front mic) pin */
4503 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4504 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4505 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4506 /* Port-C (line-in) pin */
4507 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4508 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4509 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4510 /* Port-C mixer - mute as input */
4511 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4512 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4513 /* Port-E (mic-in) pin */
4514 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4515 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4516 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4517 /* Port-E mixer - mute as input */
4518 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4519 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4520 /* Port-F (surround) */
4521 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4522 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4524 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4525 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4526 /* Analog mixer; mute as default */
4527 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4528 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4529 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4530 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4531 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4532 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4533 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4534 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4535 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4536 /* Analog Mix output amp */
4537 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4538 /* SPDIF output selector */
4539 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4540 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4541 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4545 #ifdef CONFIG_SND_HDA_POWER_SAVE
4546 static struct hda_amp_list ad1882_loopbacks[] = {
4547 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4548 { 0x20, HDA_INPUT, 1 }, /* Mic */
4549 { 0x20, HDA_INPUT, 4 }, /* Line */
4550 { 0x20, HDA_INPUT, 6 }, /* CD */
4562 static const char *ad1882_models[AD1986A_MODELS] = {
4563 [AD1882_3STACK] = "3stack",
4564 [AD1882_6STACK] = "6stack",
4568 static int patch_ad1882(struct hda_codec *codec)
4570 struct ad198x_spec *spec;
4571 int err, board_config;
4573 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4579 err = snd_hda_attach_beep_device(codec, 0x10);
4584 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4586 spec->multiout.max_channels = 6;
4587 spec->multiout.num_dacs = 3;
4588 spec->multiout.dac_nids = ad1882_dac_nids;
4589 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4590 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4591 spec->adc_nids = ad1882_adc_nids;
4592 spec->capsrc_nids = ad1882_capsrc_nids;
4593 if (codec->vendor_id == 0x11d41882)
4594 spec->input_mux = &ad1882_capture_source;
4596 spec->input_mux = &ad1882a_capture_source;
4597 spec->num_mixers = 2;
4598 spec->mixers[0] = ad1882_base_mixers;
4599 if (codec->vendor_id == 0x11d41882)
4600 spec->mixers[1] = ad1882_loopback_mixers;
4602 spec->mixers[1] = ad1882a_loopback_mixers;
4603 spec->num_init_verbs = 1;
4604 spec->init_verbs[0] = ad1882_init_verbs;
4605 spec->spdif_route = 0;
4606 #ifdef CONFIG_SND_HDA_POWER_SAVE
4607 spec->loopback.amplist = ad1882_loopbacks;
4609 spec->vmaster_nid = 0x04;
4611 codec->patch_ops = ad198x_patch_ops;
4613 /* override some parameters */
4614 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4615 ad1882_models, NULL);
4616 switch (board_config) {
4619 spec->num_mixers = 3;
4620 spec->mixers[2] = ad1882_3stack_mixers;
4621 spec->channel_mode = ad1882_modes;
4622 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4623 spec->need_dac_fix = 1;
4624 spec->multiout.max_channels = 2;
4625 spec->multiout.num_dacs = 1;
4628 spec->num_mixers = 3;
4629 spec->mixers[2] = ad1882_6stack_mixers;
4639 static struct hda_codec_preset snd_hda_preset_analog[] = {
4640 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4641 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4642 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4643 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4644 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4645 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4646 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4647 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4648 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4649 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4650 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4651 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4652 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4653 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4654 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4658 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4660 MODULE_LICENSE("GPL");
4661 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4663 static struct hda_codec_preset_list analog_list = {
4664 .preset = snd_hda_preset_analog,
4665 .owner = THIS_MODULE,
4668 static int __init patch_analog_init(void)
4670 return snd_hda_add_codec_preset(&analog_list);
4673 static void __exit patch_analog_exit(void)
4675 snd_hda_delete_codec_preset(&analog_list);
4678 module_init(patch_analog_init)
4679 module_exit(patch_analog_exit)