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>
26 #include <linux/mutex.h>
28 #include <sound/core.h>
29 #include "hda_codec.h"
30 #include "hda_local.h"
33 struct snd_kcontrol_new *mixers[5];
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 struct mutex amp_mutex; /* PCM volume/mute control mutex */
67 unsigned int spdif_route;
69 /* dynamic controls, init_verbs and input_mux */
70 struct auto_pin_cfg autocfg;
71 unsigned int num_kctl_alloc, num_kctl_used;
72 struct snd_kcontrol_new *kctl_alloc;
73 struct hda_input_mux private_imux;
74 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
76 unsigned int jack_present :1;
78 #ifdef CONFIG_SND_HDA_POWER_SAVE
79 struct hda_loopback_check loopback;
81 /* for virtual master */
82 hda_nid_t vmaster_nid;
84 const char **slave_vols;
85 const char **slave_sws;
89 * input MUX handling (common part)
91 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
93 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
94 struct ad198x_spec *spec = codec->spec;
96 return snd_hda_input_mux_info(spec->input_mux, uinfo);
99 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
101 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
102 struct ad198x_spec *spec = codec->spec;
103 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
105 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
109 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
111 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
112 struct ad198x_spec *spec = codec->spec;
113 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
115 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
116 spec->capsrc_nids[adc_idx],
117 &spec->cur_mux[adc_idx]);
121 * initialization (common callbacks)
123 static int ad198x_init(struct hda_codec *codec)
125 struct ad198x_spec *spec = codec->spec;
128 for (i = 0; i < spec->num_init_verbs; i++)
129 snd_hda_sequence_write(codec, spec->init_verbs[i]);
133 static const char *ad_slave_vols[] = {
134 "Front Playback Volume",
135 "Surround Playback Volume",
136 "Center Playback Volume",
137 "LFE Playback Volume",
138 "Side Playback Volume",
139 "Headphone Playback Volume",
140 "Mono Playback Volume",
141 "Speaker Playback Volume",
142 "IEC958 Playback Volume",
146 static const char *ad_slave_sws[] = {
147 "Front Playback Switch",
148 "Surround Playback Switch",
149 "Center Playback Switch",
150 "LFE Playback Switch",
151 "Side Playback Switch",
152 "Headphone Playback Switch",
153 "Mono Playback Switch",
154 "Speaker Playback Switch",
155 "IEC958 Playback Switch",
159 static int ad198x_build_controls(struct hda_codec *codec)
161 struct ad198x_spec *spec = codec->spec;
165 for (i = 0; i < spec->num_mixers; i++) {
166 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
170 if (spec->multiout.dig_out_nid) {
171 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
175 if (spec->dig_in_nid) {
176 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
181 /* if we have no master control, let's create it */
182 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
183 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
184 HDA_OUTPUT, spec->vmaster_tlv);
185 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
188 spec->slave_vols : ad_slave_vols));
192 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
193 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
196 spec->slave_sws : ad_slave_sws));
204 #ifdef CONFIG_SND_HDA_POWER_SAVE
205 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
207 struct ad198x_spec *spec = codec->spec;
208 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
213 * Analog playback callbacks
215 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
216 struct hda_codec *codec,
217 struct snd_pcm_substream *substream)
219 struct ad198x_spec *spec = codec->spec;
220 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
223 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
224 struct hda_codec *codec,
225 unsigned int stream_tag,
227 struct snd_pcm_substream *substream)
229 struct ad198x_spec *spec = codec->spec;
230 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
234 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
235 struct hda_codec *codec,
236 struct snd_pcm_substream *substream)
238 struct ad198x_spec *spec = codec->spec;
239 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
245 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
246 struct hda_codec *codec,
247 struct snd_pcm_substream *substream)
249 struct ad198x_spec *spec = codec->spec;
250 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
253 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
254 struct hda_codec *codec,
255 struct snd_pcm_substream *substream)
257 struct ad198x_spec *spec = codec->spec;
258 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
261 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
262 struct hda_codec *codec,
263 unsigned int stream_tag,
265 struct snd_pcm_substream *substream)
267 struct ad198x_spec *spec = codec->spec;
268 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
275 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
276 struct hda_codec *codec,
277 unsigned int stream_tag,
279 struct snd_pcm_substream *substream)
281 struct ad198x_spec *spec = codec->spec;
282 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
283 stream_tag, 0, format);
287 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
288 struct hda_codec *codec,
289 struct snd_pcm_substream *substream)
291 struct ad198x_spec *spec = codec->spec;
292 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
300 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
303 .channels_max = 6, /* changed later */
304 .nid = 0, /* fill later */
306 .open = ad198x_playback_pcm_open,
307 .prepare = ad198x_playback_pcm_prepare,
308 .cleanup = ad198x_playback_pcm_cleanup
312 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
316 .nid = 0, /* fill later */
318 .prepare = ad198x_capture_pcm_prepare,
319 .cleanup = ad198x_capture_pcm_cleanup
323 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
327 .nid = 0, /* fill later */
329 .open = ad198x_dig_playback_pcm_open,
330 .close = ad198x_dig_playback_pcm_close,
331 .prepare = ad198x_dig_playback_pcm_prepare
335 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
339 /* NID is set in alc_build_pcms */
342 static int ad198x_build_pcms(struct hda_codec *codec)
344 struct ad198x_spec *spec = codec->spec;
345 struct hda_pcm *info = spec->pcm_rec;
348 codec->pcm_info = info;
350 info->name = "AD198x Analog";
351 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
352 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
353 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
354 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
355 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
356 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
358 if (spec->multiout.dig_out_nid) {
361 info->name = "AD198x Digital";
362 info->pcm_type = HDA_PCM_TYPE_SPDIF;
363 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
364 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
365 if (spec->dig_in_nid) {
366 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
367 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
374 static void ad198x_free(struct hda_codec *codec)
376 struct ad198x_spec *spec = codec->spec;
379 if (spec->kctl_alloc) {
380 for (i = 0; i < spec->num_kctl_used; i++)
381 kfree(spec->kctl_alloc[i].name);
382 kfree(spec->kctl_alloc);
387 static struct hda_codec_ops ad198x_patch_ops = {
388 .build_controls = ad198x_build_controls,
389 .build_pcms = ad198x_build_pcms,
392 #ifdef CONFIG_SND_HDA_POWER_SAVE
393 .check_power_status = ad198x_check_power_status,
400 * the private value = nid | (invert << 8)
402 #define ad198x_eapd_info snd_ctl_boolean_mono_info
404 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
405 struct snd_ctl_elem_value *ucontrol)
407 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
408 struct ad198x_spec *spec = codec->spec;
409 int invert = (kcontrol->private_value >> 8) & 1;
411 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
413 ucontrol->value.integer.value[0] = spec->cur_eapd;
417 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
420 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
421 struct ad198x_spec *spec = codec->spec;
422 int invert = (kcontrol->private_value >> 8) & 1;
423 hda_nid_t nid = kcontrol->private_value & 0xff;
425 eapd = !!ucontrol->value.integer.value[0];
428 if (eapd == spec->cur_eapd)
430 spec->cur_eapd = eapd;
431 snd_hda_codec_write_cache(codec, nid,
432 0, AC_VERB_SET_EAPD_BTLENABLE,
437 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
438 struct snd_ctl_elem_info *uinfo);
439 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
440 struct snd_ctl_elem_value *ucontrol);
441 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
442 struct snd_ctl_elem_value *ucontrol);
449 #define AD1986A_SPDIF_OUT 0x02
450 #define AD1986A_FRONT_DAC 0x03
451 #define AD1986A_SURR_DAC 0x04
452 #define AD1986A_CLFE_DAC 0x05
453 #define AD1986A_ADC 0x06
455 static hda_nid_t ad1986a_dac_nids[3] = {
456 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
458 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
459 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
461 static struct hda_input_mux ad1986a_capture_source = {
475 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
476 .ops = &snd_hda_bind_vol,
478 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
479 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
480 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
485 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
486 .ops = &snd_hda_bind_sw,
488 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
489 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
490 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
498 static struct snd_kcontrol_new ad1986a_mixers[] = {
500 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
502 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
503 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
504 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
505 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
506 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
507 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
508 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
509 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
510 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
511 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
512 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
513 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
514 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
515 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
516 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
517 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
518 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
519 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
520 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
521 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
522 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
523 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
524 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
525 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
526 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
527 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
528 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
531 .name = "Capture Source",
532 .info = ad198x_mux_enum_info,
533 .get = ad198x_mux_enum_get,
534 .put = ad198x_mux_enum_put,
536 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
540 /* additional mixers for 3stack mode */
541 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
544 .name = "Channel Mode",
545 .info = ad198x_ch_mode_info,
546 .get = ad198x_ch_mode_get,
547 .put = ad198x_ch_mode_put,
552 /* laptop model - 2ch only */
553 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
555 /* master controls both pins 0x1a and 0x1b */
556 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
557 .ops = &snd_hda_bind_vol,
559 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
560 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
565 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
566 .ops = &snd_hda_bind_sw,
568 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
569 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
574 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
575 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
576 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
577 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
578 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
579 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
580 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
581 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
582 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
583 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
584 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
585 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
586 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
587 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
588 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
589 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
590 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
591 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
592 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
593 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
595 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
596 .name = "Capture Source",
597 .info = ad198x_mux_enum_info,
598 .get = ad198x_mux_enum_get,
599 .put = ad198x_mux_enum_put,
604 /* laptop-eapd model - 2ch only */
606 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
610 { "Internal Mic", 0x4 },
615 static struct hda_input_mux ad1986a_automic_capture_source = {
623 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
624 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
625 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
626 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
627 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
628 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
629 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
630 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
631 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
632 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
635 .name = "Capture Source",
636 .info = ad198x_mux_enum_info,
637 .get = ad198x_mux_enum_get,
638 .put = ad198x_mux_enum_put,
641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
642 .name = "External Amplifier",
643 .info = ad198x_eapd_info,
644 .get = ad198x_eapd_get,
645 .put = ad198x_eapd_put,
646 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
651 /* re-connect the mic boost input according to the jack sensing */
652 static void ad1986a_automic(struct hda_codec *codec)
654 unsigned int present;
655 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
656 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
657 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
658 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
661 #define AD1986A_MIC_EVENT 0x36
663 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
666 if ((res >> 26) != AD1986A_MIC_EVENT)
668 ad1986a_automic(codec);
671 static int ad1986a_automic_init(struct hda_codec *codec)
674 ad1986a_automic(codec);
678 /* laptop-automute - 2ch only */
680 static void ad1986a_update_hp(struct hda_codec *codec)
682 struct ad198x_spec *spec = codec->spec;
685 if (spec->jack_present)
686 mute = HDA_AMP_MUTE; /* mute internal speaker */
688 /* unmute internal speaker if necessary */
689 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
690 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
694 static void ad1986a_hp_automute(struct hda_codec *codec)
696 struct ad198x_spec *spec = codec->spec;
697 unsigned int present;
699 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
700 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
701 spec->jack_present = !(present & 0x80000000);
702 ad1986a_update_hp(codec);
705 #define AD1986A_HP_EVENT 0x37
707 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
709 if ((res >> 26) != AD1986A_HP_EVENT)
711 ad1986a_hp_automute(codec);
714 static int ad1986a_hp_init(struct hda_codec *codec)
717 ad1986a_hp_automute(codec);
721 /* bind hp and internal speaker mute (with plug check) */
722 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
723 struct snd_ctl_elem_value *ucontrol)
725 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
726 long *valp = ucontrol->value.integer.value;
729 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
731 valp[0] ? 0 : HDA_AMP_MUTE);
732 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
734 valp[1] ? 0 : HDA_AMP_MUTE);
736 ad1986a_update_hp(codec);
740 static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
741 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
744 .name = "Master Playback Switch",
745 .info = snd_hda_mixer_amp_switch_info,
746 .get = snd_hda_mixer_amp_switch_get,
747 .put = ad1986a_hp_master_sw_put,
748 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
750 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
751 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
752 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
753 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
754 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
755 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
756 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
757 HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
758 HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
759 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
760 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
762 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
763 .name = "Capture Source",
764 .info = ad198x_mux_enum_info,
765 .get = ad198x_mux_enum_get,
766 .put = ad198x_mux_enum_put,
769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
770 .name = "External Amplifier",
771 .info = ad198x_eapd_info,
772 .get = ad198x_eapd_get,
773 .put = ad198x_eapd_put,
774 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
780 * initialization verbs
782 static struct hda_verb ad1986a_init_verbs[] = {
783 /* Front, Surround, CLFE DAC; mute as default */
784 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
785 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
786 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
788 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
789 /* HP, Line-Out, Surround, CLFE selectors */
790 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
791 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
792 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
793 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
795 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
796 /* Mic selector: Mic 1/2 pin */
797 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
798 /* Line-in selector: Line-in */
799 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
801 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
802 /* Record selector: mic */
803 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
804 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
805 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
806 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
807 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
808 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
809 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
811 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
812 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
813 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
814 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
815 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
816 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
817 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
819 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
820 /* Front, Surround, CLFE Pins */
821 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
822 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
823 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
825 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
827 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
828 /* Line, Aux, CD, Beep-In Pin */
829 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
830 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
831 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
832 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
833 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
837 static struct hda_verb ad1986a_ch2_init[] = {
838 /* Surround out -> Line In */
839 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
840 /* Line-in selectors */
841 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
843 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
844 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
845 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
849 static struct hda_verb ad1986a_ch4_init[] = {
850 /* Surround out -> Surround */
851 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
852 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
854 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
855 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
859 static struct hda_verb ad1986a_ch6_init[] = {
860 /* Surround out -> Surround out */
861 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
862 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
864 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
865 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
869 static struct hda_channel_mode ad1986a_modes[3] = {
870 { 2, ad1986a_ch2_init },
871 { 4, ad1986a_ch4_init },
872 { 6, ad1986a_ch6_init },
875 /* eapd initialization */
876 static struct hda_verb ad1986a_eapd_init_verbs[] = {
877 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
881 static struct hda_verb ad1986a_automic_verbs[] = {
882 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
883 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
884 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
885 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
886 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
890 /* Ultra initialization */
891 static struct hda_verb ad1986a_ultra_init[] = {
892 /* eapd initialization */
893 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
895 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
896 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
897 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
901 /* pin sensing on HP jack */
902 static struct hda_verb ad1986a_hp_init_verbs[] = {
903 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
914 AD1986A_LAPTOP_AUTOMUTE,
919 static const char *ad1986a_models[AD1986A_MODELS] = {
920 [AD1986A_6STACK] = "6stack",
921 [AD1986A_3STACK] = "3stack",
922 [AD1986A_LAPTOP] = "laptop",
923 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
924 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
925 [AD1986A_ULTRA] = "ultra",
928 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
929 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
930 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
931 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
932 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
933 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
934 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
935 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
936 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
937 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
938 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
939 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
940 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
941 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
942 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
943 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
944 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
945 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
946 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
947 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
948 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
949 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
950 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
951 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
952 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
953 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
954 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
955 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
956 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
960 #ifdef CONFIG_SND_HDA_POWER_SAVE
961 static struct hda_amp_list ad1986a_loopbacks[] = {
962 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
963 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
964 { 0x15, HDA_OUTPUT, 0 }, /* CD */
965 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
966 { 0x17, HDA_OUTPUT, 0 }, /* Line */
971 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
973 unsigned int conf = snd_hda_codec_read(codec, nid, 0,
974 AC_VERB_GET_CONFIG_DEFAULT, 0);
975 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
978 static int patch_ad1986a(struct hda_codec *codec)
980 struct ad198x_spec *spec;
983 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
989 spec->multiout.max_channels = 6;
990 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
991 spec->multiout.dac_nids = ad1986a_dac_nids;
992 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
993 spec->num_adc_nids = 1;
994 spec->adc_nids = ad1986a_adc_nids;
995 spec->capsrc_nids = ad1986a_capsrc_nids;
996 spec->input_mux = &ad1986a_capture_source;
997 spec->num_mixers = 1;
998 spec->mixers[0] = ad1986a_mixers;
999 spec->num_init_verbs = 1;
1000 spec->init_verbs[0] = ad1986a_init_verbs;
1001 #ifdef CONFIG_SND_HDA_POWER_SAVE
1002 spec->loopback.amplist = ad1986a_loopbacks;
1004 spec->vmaster_nid = 0x1b;
1006 codec->patch_ops = ad198x_patch_ops;
1008 /* override some parameters */
1009 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1012 switch (board_config) {
1013 case AD1986A_3STACK:
1014 spec->num_mixers = 2;
1015 spec->mixers[1] = ad1986a_3st_mixers;
1016 spec->num_init_verbs = 2;
1017 spec->init_verbs[1] = ad1986a_ch2_init;
1018 spec->channel_mode = ad1986a_modes;
1019 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1020 spec->need_dac_fix = 1;
1021 spec->multiout.max_channels = 2;
1022 spec->multiout.num_dacs = 1;
1024 case AD1986A_LAPTOP:
1025 spec->mixers[0] = ad1986a_laptop_mixers;
1026 spec->multiout.max_channels = 2;
1027 spec->multiout.num_dacs = 1;
1028 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1030 case AD1986A_LAPTOP_EAPD:
1031 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1032 spec->num_init_verbs = 3;
1033 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1034 spec->init_verbs[2] = ad1986a_automic_verbs;
1035 spec->multiout.max_channels = 2;
1036 spec->multiout.num_dacs = 1;
1037 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1038 if (!is_jack_available(codec, 0x25))
1039 spec->multiout.dig_out_nid = 0;
1040 spec->input_mux = &ad1986a_automic_capture_source;
1041 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1042 codec->patch_ops.init = ad1986a_automic_init;
1044 case AD1986A_LAPTOP_AUTOMUTE:
1045 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1046 spec->num_init_verbs = 3;
1047 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1048 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1049 spec->multiout.max_channels = 2;
1050 spec->multiout.num_dacs = 1;
1051 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1052 if (!is_jack_available(codec, 0x25))
1053 spec->multiout.dig_out_nid = 0;
1054 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1055 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1056 codec->patch_ops.init = ad1986a_hp_init;
1059 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1060 spec->num_init_verbs = 2;
1061 spec->init_verbs[1] = ad1986a_ultra_init;
1062 spec->multiout.max_channels = 2;
1063 spec->multiout.num_dacs = 1;
1064 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1065 spec->multiout.dig_out_nid = 0;
1069 /* AD1986A has a hardware problem that it can't share a stream
1070 * with multiple output pins. The copy of front to surrounds
1071 * causes noisy or silent outputs at a certain timing, e.g.
1072 * changing the volume.
1073 * So, let's disable the shared stream.
1075 spec->multiout.no_share_stream = 1;
1084 #define AD1983_SPDIF_OUT 0x02
1085 #define AD1983_DAC 0x03
1086 #define AD1983_ADC 0x04
1088 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1089 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1090 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1092 static struct hda_input_mux ad1983_capture_source = {
1098 { "Mix Mono", 0x3 },
1103 * SPDIF playback route
1105 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1107 static char *texts[] = { "PCM", "ADC" };
1109 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1111 uinfo->value.enumerated.items = 2;
1112 if (uinfo->value.enumerated.item > 1)
1113 uinfo->value.enumerated.item = 1;
1114 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1118 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1120 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1121 struct ad198x_spec *spec = codec->spec;
1123 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1127 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1129 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1130 struct ad198x_spec *spec = codec->spec;
1132 if (ucontrol->value.enumerated.item[0] > 1)
1134 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1135 spec->spdif_route = ucontrol->value.enumerated.item[0];
1136 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1137 AC_VERB_SET_CONNECT_SEL,
1144 static struct snd_kcontrol_new ad1983_mixers[] = {
1145 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1146 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1147 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1148 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1149 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1150 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1151 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1152 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1153 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1154 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1155 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1156 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1157 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
1158 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
1159 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1160 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1161 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1163 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1164 .name = "Capture Source",
1165 .info = ad198x_mux_enum_info,
1166 .get = ad198x_mux_enum_get,
1167 .put = ad198x_mux_enum_put,
1170 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1171 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1172 .info = ad1983_spdif_route_info,
1173 .get = ad1983_spdif_route_get,
1174 .put = ad1983_spdif_route_put,
1179 static struct hda_verb ad1983_init_verbs[] = {
1180 /* Front, HP, Mono; mute as default */
1181 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1182 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1183 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1184 /* Beep, PCM, Mic, Line-In: mute */
1185 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1186 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1187 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1188 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1189 /* Front, HP selectors; from Mix */
1190 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1191 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1192 /* Mono selector; from Mix */
1193 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1194 /* Mic selector; Mic */
1195 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1196 /* Line-in selector: Line-in */
1197 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1198 /* Mic boost: 0dB */
1199 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1200 /* Record selector: mic */
1201 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1202 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1203 /* SPDIF route: PCM */
1204 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1206 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1208 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1210 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1212 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1214 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1218 #ifdef CONFIG_SND_HDA_POWER_SAVE
1219 static struct hda_amp_list ad1983_loopbacks[] = {
1220 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1221 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1226 static int patch_ad1983(struct hda_codec *codec)
1228 struct ad198x_spec *spec;
1230 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1236 spec->multiout.max_channels = 2;
1237 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1238 spec->multiout.dac_nids = ad1983_dac_nids;
1239 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1240 spec->num_adc_nids = 1;
1241 spec->adc_nids = ad1983_adc_nids;
1242 spec->capsrc_nids = ad1983_capsrc_nids;
1243 spec->input_mux = &ad1983_capture_source;
1244 spec->num_mixers = 1;
1245 spec->mixers[0] = ad1983_mixers;
1246 spec->num_init_verbs = 1;
1247 spec->init_verbs[0] = ad1983_init_verbs;
1248 spec->spdif_route = 0;
1249 #ifdef CONFIG_SND_HDA_POWER_SAVE
1250 spec->loopback.amplist = ad1983_loopbacks;
1252 spec->vmaster_nid = 0x05;
1254 codec->patch_ops = ad198x_patch_ops;
1261 * AD1981 HD specific
1264 #define AD1981_SPDIF_OUT 0x02
1265 #define AD1981_DAC 0x03
1266 #define AD1981_ADC 0x04
1268 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1269 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1270 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1272 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1273 static struct hda_input_mux ad1981_capture_source = {
1276 { "Front Mic", 0x0 },
1279 { "Mix Mono", 0x3 },
1286 static struct snd_kcontrol_new ad1981_mixers[] = {
1287 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1288 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1289 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1290 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1291 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1292 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1293 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1294 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1295 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1296 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1297 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1298 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1299 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1300 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1301 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1302 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1303 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1304 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1305 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1306 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
1307 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1308 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1309 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1310 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1312 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1313 .name = "Capture Source",
1314 .info = ad198x_mux_enum_info,
1315 .get = ad198x_mux_enum_get,
1316 .put = ad198x_mux_enum_put,
1318 /* identical with AD1983 */
1320 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1321 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1322 .info = ad1983_spdif_route_info,
1323 .get = ad1983_spdif_route_get,
1324 .put = ad1983_spdif_route_put,
1329 static struct hda_verb ad1981_init_verbs[] = {
1330 /* Front, HP, Mono; mute as default */
1331 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1332 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1333 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1334 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1335 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1336 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1337 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1338 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1339 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1340 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1341 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1342 /* Front, HP selectors; from Mix */
1343 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1344 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1345 /* Mono selector; from Mix */
1346 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1347 /* Mic Mixer; select Front Mic */
1348 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1349 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1350 /* Mic boost: 0dB */
1351 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1352 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1353 /* Record selector: Front mic */
1354 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1355 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1356 /* SPDIF route: PCM */
1357 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1359 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1361 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1363 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1364 /* Front & Rear Mic Pins */
1365 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1366 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1368 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1370 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1371 /* Line-Out as Input: disabled */
1372 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1376 #ifdef CONFIG_SND_HDA_POWER_SAVE
1377 static struct hda_amp_list ad1981_loopbacks[] = {
1378 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1379 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1380 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1381 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1382 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1388 * Patch for HP nx6320
1390 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1391 * speaker output enabled _and_ mute-LED off.
1394 #define AD1981_HP_EVENT 0x37
1395 #define AD1981_MIC_EVENT 0x38
1397 static struct hda_verb ad1981_hp_init_verbs[] = {
1398 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1399 /* pin sensing on HP and Mic jacks */
1400 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1401 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1405 /* turn on/off EAPD (+ mute HP) as a master switch */
1406 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1407 struct snd_ctl_elem_value *ucontrol)
1409 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1410 struct ad198x_spec *spec = codec->spec;
1412 if (! ad198x_eapd_put(kcontrol, ucontrol))
1414 /* change speaker pin appropriately */
1415 snd_hda_codec_write(codec, 0x05, 0,
1416 AC_VERB_SET_PIN_WIDGET_CONTROL,
1417 spec->cur_eapd ? PIN_OUT : 0);
1418 /* toggle HP mute appropriately */
1419 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1421 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1425 /* bind volumes of both NID 0x05 and 0x06 */
1426 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1427 .ops = &snd_hda_bind_vol,
1429 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1430 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1435 /* mute internal speaker if HP is plugged */
1436 static void ad1981_hp_automute(struct hda_codec *codec)
1438 unsigned int present;
1440 present = snd_hda_codec_read(codec, 0x06, 0,
1441 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1442 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1443 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1446 /* toggle input of built-in and mic jack appropriately */
1447 static void ad1981_hp_automic(struct hda_codec *codec)
1449 static struct hda_verb mic_jack_on[] = {
1450 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1451 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1454 static struct hda_verb mic_jack_off[] = {
1455 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1456 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1459 unsigned int present;
1461 present = snd_hda_codec_read(codec, 0x08, 0,
1462 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1464 snd_hda_sequence_write(codec, mic_jack_on);
1466 snd_hda_sequence_write(codec, mic_jack_off);
1469 /* unsolicited event for HP jack sensing */
1470 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1475 case AD1981_HP_EVENT:
1476 ad1981_hp_automute(codec);
1478 case AD1981_MIC_EVENT:
1479 ad1981_hp_automic(codec);
1484 static struct hda_input_mux ad1981_hp_capture_source = {
1488 { "Docking-Station", 0x1 },
1493 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1494 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1496 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1497 .name = "Master Playback Switch",
1498 .info = ad198x_eapd_info,
1499 .get = ad198x_eapd_get,
1500 .put = ad1981_hp_master_sw_put,
1501 .private_value = 0x05,
1503 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1506 /* FIXME: analog mic/line loopback doesn't work with my tests...
1507 * (although recording is OK)
1509 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1512 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1513 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1514 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1515 /* FIXME: does this laptop have analog CD connection? */
1516 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1517 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1519 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1520 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1521 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1522 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1525 .name = "Capture Source",
1526 .info = ad198x_mux_enum_info,
1527 .get = ad198x_mux_enum_get,
1528 .put = ad198x_mux_enum_put,
1533 /* initialize jack-sensing, too */
1534 static int ad1981_hp_init(struct hda_codec *codec)
1537 ad1981_hp_automute(codec);
1538 ad1981_hp_automic(codec);
1542 /* configuration for Toshiba Laptops */
1543 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1544 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1545 /* pin sensing on HP and Mic jacks */
1546 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1547 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1551 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1552 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1553 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1557 /* configuration for Lenovo Thinkpad T60 */
1558 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1559 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1560 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1561 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1562 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1563 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1564 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1565 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1566 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1567 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1568 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1569 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572 .name = "Capture Source",
1573 .info = ad198x_mux_enum_info,
1574 .get = ad198x_mux_enum_get,
1575 .put = ad198x_mux_enum_put,
1577 /* identical with AD1983 */
1579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1580 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1581 .info = ad1983_spdif_route_info,
1582 .get = ad1983_spdif_route_get,
1583 .put = ad1983_spdif_route_put,
1588 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1606 static const char *ad1981_models[AD1981_MODELS] = {
1608 [AD1981_THINKPAD] = "thinkpad",
1609 [AD1981_BASIC] = "basic",
1610 [AD1981_TOSHIBA] = "toshiba"
1613 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1614 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1616 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
1617 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1618 /* Lenovo Thinkpad T60/X60/Z6xx */
1619 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
1620 /* HP nx6320 (reversed SSID, H/W bug) */
1621 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1625 static int patch_ad1981(struct hda_codec *codec)
1627 struct ad198x_spec *spec;
1630 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1636 spec->multiout.max_channels = 2;
1637 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1638 spec->multiout.dac_nids = ad1981_dac_nids;
1639 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1640 spec->num_adc_nids = 1;
1641 spec->adc_nids = ad1981_adc_nids;
1642 spec->capsrc_nids = ad1981_capsrc_nids;
1643 spec->input_mux = &ad1981_capture_source;
1644 spec->num_mixers = 1;
1645 spec->mixers[0] = ad1981_mixers;
1646 spec->num_init_verbs = 1;
1647 spec->init_verbs[0] = ad1981_init_verbs;
1648 spec->spdif_route = 0;
1649 #ifdef CONFIG_SND_HDA_POWER_SAVE
1650 spec->loopback.amplist = ad1981_loopbacks;
1652 spec->vmaster_nid = 0x05;
1654 codec->patch_ops = ad198x_patch_ops;
1656 /* override some parameters */
1657 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1660 switch (board_config) {
1662 spec->mixers[0] = ad1981_hp_mixers;
1663 spec->num_init_verbs = 2;
1664 spec->init_verbs[1] = ad1981_hp_init_verbs;
1665 spec->multiout.dig_out_nid = 0;
1666 spec->input_mux = &ad1981_hp_capture_source;
1668 codec->patch_ops.init = ad1981_hp_init;
1669 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1671 case AD1981_THINKPAD:
1672 spec->mixers[0] = ad1981_thinkpad_mixers;
1673 spec->input_mux = &ad1981_thinkpad_capture_source;
1675 case AD1981_TOSHIBA:
1676 spec->mixers[0] = ad1981_hp_mixers;
1677 spec->mixers[1] = ad1981_toshiba_mixers;
1678 spec->num_init_verbs = 2;
1679 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1680 spec->multiout.dig_out_nid = 0;
1681 spec->input_mux = &ad1981_hp_capture_source;
1682 codec->patch_ops.init = ad1981_hp_init;
1683 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1693 * Output pins and routes
1695 * Pin Mix Sel DAC (*)
1696 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1697 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1698 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1699 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1700 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1701 * port-F 0x16 (mute) <- 0x2a <- 06
1702 * port-G 0x24 (mute) <- 0x27 <- 05
1703 * port-H 0x25 (mute) <- 0x28 <- 0a
1704 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1706 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1707 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1709 * Input pins and routes
1711 * pin boost mix input # / adc input #
1712 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1713 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1714 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1715 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1716 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1717 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1718 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1719 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1723 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1724 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1726 * Inputs of Analog Mix (0x20)
1727 * 0:Port-B (front mic)
1728 * 1:Port-C/G/H (line-in)
1730 * 3:Port-D (line-in/2)
1731 * 4:Port-E/G/H (mic-in)
1732 * 5:Port-F (mic2-in)
1738 * 1:Port-B (front mic-in)
1739 * 2:Port-C (line-in)
1740 * 3:Port-F (mic2-in)
1745 * 8:Port-D (line-in/2)
1748 * Proposed pin assignments by the datasheet
1751 * Port-A front headphone
1761 * Port-A front headphone
1763 * C rear line-in/surround
1765 * E rear mic-in/CLFE
1771 * D internal speaker (with EAPD)
1772 * E/F quad mic array
1788 /* reivision id to check workarounds */
1789 #define AD1988A_REV2 0x100200
1791 #define is_rev2(codec) \
1792 ((codec)->vendor_id == 0x11d41988 && \
1793 (codec)->revision_id == AD1988A_REV2)
1799 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1800 0x04, 0x06, 0x05, 0x0a
1803 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1807 /* for AD1988A revision-2, DAC2-4 are swapped */
1808 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1809 0x04, 0x05, 0x0a, 0x06
1812 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1816 static hda_nid_t ad1988_adc_nids[3] = {
1820 static hda_nid_t ad1988_capsrc_nids[3] = {
1824 #define AD1988_SPDIF_OUT 0x02
1825 #define AD1988_SPDIF_IN 0x07
1827 static struct hda_input_mux ad1988_6stack_capture_source = {
1830 { "Front Mic", 0x1 }, /* port-B */
1831 { "Line", 0x2 }, /* port-C */
1832 { "Mic", 0x4 }, /* port-E */
1838 static struct hda_input_mux ad1988_laptop_capture_source = {
1841 { "Mic/Line", 0x1 }, /* port-B */
1849 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1850 struct snd_ctl_elem_info *uinfo)
1852 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1853 struct ad198x_spec *spec = codec->spec;
1854 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1855 spec->num_channel_mode);
1858 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1859 struct snd_ctl_elem_value *ucontrol)
1861 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1862 struct ad198x_spec *spec = codec->spec;
1863 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1864 spec->num_channel_mode, spec->multiout.max_channels);
1867 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1868 struct snd_ctl_elem_value *ucontrol)
1870 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1871 struct ad198x_spec *spec = codec->spec;
1872 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1873 spec->num_channel_mode,
1874 &spec->multiout.max_channels);
1875 if (err >= 0 && spec->need_dac_fix)
1876 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1881 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1882 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1883 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1884 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1885 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1886 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1890 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
1891 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1892 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1893 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1894 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
1895 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1899 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
1900 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1901 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1902 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1903 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1904 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1905 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1906 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1908 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1909 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1910 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1911 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1912 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1913 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1914 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1915 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1917 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1918 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1920 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1921 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1923 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1924 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1930 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
1931 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1932 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1933 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1934 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1938 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
1939 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1940 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1941 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
1942 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
1946 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
1947 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1948 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
1949 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
1950 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
1951 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1952 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1954 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1955 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1956 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1957 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1958 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1959 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1960 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1961 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1963 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1964 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1966 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1967 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1969 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1970 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1972 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1973 .name = "Channel Mode",
1974 .info = ad198x_ch_mode_info,
1975 .get = ad198x_ch_mode_get,
1976 .put = ad198x_ch_mode_put,
1983 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1984 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1985 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1986 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1988 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1989 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1990 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1991 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1992 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1993 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1995 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1996 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1998 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1999 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2001 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2005 .name = "External Amplifier",
2006 .info = ad198x_eapd_info,
2007 .get = ad198x_eapd_get,
2008 .put = ad198x_eapd_put,
2009 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2016 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2017 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2018 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2019 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2020 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2021 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2022 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2024 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2025 /* The multiple "Capture Source" controls confuse alsamixer
2026 * So call somewhat different..
2028 /* .name = "Capture Source", */
2029 .name = "Input Source",
2031 .info = ad198x_mux_enum_info,
2032 .get = ad198x_mux_enum_get,
2033 .put = ad198x_mux_enum_put,
2038 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2039 struct snd_ctl_elem_info *uinfo)
2041 static char *texts[] = {
2042 "PCM", "ADC1", "ADC2", "ADC3"
2044 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2046 uinfo->value.enumerated.items = 4;
2047 if (uinfo->value.enumerated.item >= 4)
2048 uinfo->value.enumerated.item = 3;
2049 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2053 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2054 struct snd_ctl_elem_value *ucontrol)
2056 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2059 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2062 ucontrol->value.enumerated.item[0] = 0;
2064 sel = snd_hda_codec_read(codec, 0x0b, 0,
2065 AC_VERB_GET_CONNECT_SEL, 0);
2070 ucontrol->value.enumerated.item[0] = sel;
2075 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2076 struct snd_ctl_elem_value *ucontrol)
2078 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2079 unsigned int val, sel;
2082 val = ucontrol->value.enumerated.item[0];
2086 sel = snd_hda_codec_read(codec, 0x1d, 0,
2087 AC_VERB_GET_AMP_GAIN_MUTE,
2089 change = sel & 0x80;
2091 snd_hda_codec_write_cache(codec, 0x1d, 0,
2092 AC_VERB_SET_AMP_GAIN_MUTE,
2094 snd_hda_codec_write_cache(codec, 0x1d, 0,
2095 AC_VERB_SET_AMP_GAIN_MUTE,
2099 sel = snd_hda_codec_read(codec, 0x1d, 0,
2100 AC_VERB_GET_AMP_GAIN_MUTE,
2101 AC_AMP_GET_INPUT | 0x01);
2102 change = sel & 0x80;
2104 snd_hda_codec_write_cache(codec, 0x1d, 0,
2105 AC_VERB_SET_AMP_GAIN_MUTE,
2107 snd_hda_codec_write_cache(codec, 0x1d, 0,
2108 AC_VERB_SET_AMP_GAIN_MUTE,
2111 sel = snd_hda_codec_read(codec, 0x0b, 0,
2112 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2113 change |= sel != val;
2115 snd_hda_codec_write_cache(codec, 0x0b, 0,
2116 AC_VERB_SET_CONNECT_SEL,
2122 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2123 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2125 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2126 .name = "IEC958 Playback Source",
2127 .info = ad1988_spdif_playback_source_info,
2128 .get = ad1988_spdif_playback_source_get,
2129 .put = ad1988_spdif_playback_source_put,
2134 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2135 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2141 * initialization verbs
2145 * for 6-stack (+dig)
2147 static struct hda_verb ad1988_6stack_init_verbs[] = {
2148 /* Front, Surround, CLFE, side DAC; unmute as default */
2149 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2150 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2151 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2152 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2153 /* Port-A front headphon path */
2154 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2155 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2156 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2157 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2158 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2159 /* Port-D line-out path */
2160 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2161 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2162 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2163 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2164 /* Port-F surround path */
2165 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2166 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2167 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2168 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2169 /* Port-G CLFE path */
2170 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2171 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2172 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2173 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2174 /* Port-H side path */
2175 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2176 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2177 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2178 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2180 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2181 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2182 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2183 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2184 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2185 /* Port-B front mic-in path */
2186 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2187 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2188 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2189 /* Port-C line-in path */
2190 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2191 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2192 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2193 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2194 /* Port-E mic-in path */
2195 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2196 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2197 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2198 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2199 /* Analog CD Input */
2200 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2205 static struct hda_verb ad1988_capture_init_verbs[] = {
2206 /* mute analog mix */
2207 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2208 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2209 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2210 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2211 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2212 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2213 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2214 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2215 /* select ADCs - front-mic */
2216 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2217 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2218 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2220 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2221 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2222 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2227 static struct hda_verb ad1988_spdif_init_verbs[] = {
2229 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2230 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2231 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2232 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2234 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2240 * verbs for 3stack (+dig)
2242 static struct hda_verb ad1988_3stack_ch2_init[] = {
2243 /* set port-C to line-in */
2244 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2245 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2246 /* set port-E to mic-in */
2247 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2248 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2252 static struct hda_verb ad1988_3stack_ch6_init[] = {
2253 /* set port-C to surround out */
2254 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2255 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2256 /* set port-E to CLFE out */
2257 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2258 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2262 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2263 { 2, ad1988_3stack_ch2_init },
2264 { 6, ad1988_3stack_ch6_init },
2267 static struct hda_verb ad1988_3stack_init_verbs[] = {
2268 /* Front, Surround, CLFE, side DAC; unmute as default */
2269 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2270 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2271 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2272 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2273 /* Port-A front headphon path */
2274 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2275 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2276 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2277 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2278 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2279 /* Port-D line-out path */
2280 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2281 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2282 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2283 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2285 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2286 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2287 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2288 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2289 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2290 /* Port-B front mic-in path */
2291 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2292 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2293 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2294 /* Port-C line-in/surround path - 6ch mode as default */
2295 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2296 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2297 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2298 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2299 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2300 /* Port-E mic-in/CLFE path - 6ch mode as default */
2301 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2302 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2303 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2304 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2305 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2306 /* mute analog mix */
2307 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2308 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2309 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2310 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2311 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2312 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2313 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2314 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2315 /* select ADCs - front-mic */
2316 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2317 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2318 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2320 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2321 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2322 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2327 * verbs for laptop mode (+dig)
2329 static struct hda_verb ad1988_laptop_hp_on[] = {
2330 /* unmute port-A and mute port-D */
2331 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2332 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2335 static struct hda_verb ad1988_laptop_hp_off[] = {
2336 /* mute port-A and unmute port-D */
2337 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2338 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2342 #define AD1988_HP_EVENT 0x01
2344 static struct hda_verb ad1988_laptop_init_verbs[] = {
2345 /* Front, Surround, CLFE, side DAC; unmute as default */
2346 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2347 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2348 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2349 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2350 /* Port-A front headphon path */
2351 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2352 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2353 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2354 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2355 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2356 /* unsolicited event for pin-sense */
2357 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2358 /* Port-D line-out path + EAPD */
2359 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2360 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2361 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2362 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2363 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2365 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2366 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2367 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2368 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2369 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2370 /* Port-B mic-in path */
2371 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2372 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2373 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2374 /* Port-C docking station - try to output */
2375 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2376 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2377 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2378 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2379 /* mute analog mix */
2380 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2381 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2382 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2383 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2384 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2385 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2388 /* select ADCs - mic */
2389 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2390 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2391 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2393 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2394 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2395 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2399 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2401 if ((res >> 26) != AD1988_HP_EVENT)
2403 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2404 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2406 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2409 #ifdef CONFIG_SND_HDA_POWER_SAVE
2410 static struct hda_amp_list ad1988_loopbacks[] = {
2411 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2412 { 0x20, HDA_INPUT, 1 }, /* Line */
2413 { 0x20, HDA_INPUT, 4 }, /* Mic */
2414 { 0x20, HDA_INPUT, 6 }, /* CD */
2420 * Automatic parse of I/O pins from the BIOS configuration
2423 #define NUM_CONTROL_ALLOC 32
2424 #define NUM_VERB_ALLOC 32
2431 static struct snd_kcontrol_new ad1988_control_templates[] = {
2432 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2433 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2434 HDA_BIND_MUTE(NULL, 0, 0, 0),
2437 /* add dynamic controls */
2438 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2441 struct snd_kcontrol_new *knew;
2443 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
2444 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
2446 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
2449 if (spec->kctl_alloc) {
2450 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2451 kfree(spec->kctl_alloc);
2453 spec->kctl_alloc = knew;
2454 spec->num_kctl_alloc = num;
2457 knew = &spec->kctl_alloc[spec->num_kctl_used];
2458 *knew = ad1988_control_templates[type];
2459 knew->name = kstrdup(name, GFP_KERNEL);
2462 knew->private_value = val;
2463 spec->num_kctl_used++;
2467 #define AD1988_PIN_CD_NID 0x18
2468 #define AD1988_PIN_BEEP_NID 0x10
2470 static hda_nid_t ad1988_mixer_nids[8] = {
2471 /* A B C D E F G H */
2472 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2475 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2477 static hda_nid_t idx_to_dac[8] = {
2478 /* A B C D E F G H */
2479 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2481 static hda_nid_t idx_to_dac_rev2[8] = {
2482 /* A B C D E F G H */
2483 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2486 return idx_to_dac_rev2[idx];
2488 return idx_to_dac[idx];
2491 static hda_nid_t ad1988_boost_nids[8] = {
2492 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2495 static int ad1988_pin_idx(hda_nid_t nid)
2497 static hda_nid_t ad1988_io_pins[8] = {
2498 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2501 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2502 if (ad1988_io_pins[i] == nid)
2504 return 0; /* should be -1 */
2507 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2509 static int loopback_idx[8] = {
2510 2, 0, 1, 3, 4, 5, 1, 4
2513 case AD1988_PIN_CD_NID:
2516 return loopback_idx[ad1988_pin_idx(nid)];
2520 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2522 static int adc_idx[8] = {
2523 0, 1, 2, 8, 4, 3, 6, 7
2526 case AD1988_PIN_CD_NID:
2529 return adc_idx[ad1988_pin_idx(nid)];
2533 /* fill in the dac_nids table from the parsed pin configuration */
2534 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2535 const struct auto_pin_cfg *cfg)
2537 struct ad198x_spec *spec = codec->spec;
2540 spec->multiout.dac_nids = spec->private_dac_nids;
2542 /* check the pins hardwired to audio widget */
2543 for (i = 0; i < cfg->line_outs; i++) {
2544 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2545 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2547 spec->multiout.num_dacs = cfg->line_outs;
2551 /* add playback controls from the parsed DAC table */
2552 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2553 const struct auto_pin_cfg *cfg)
2556 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2560 for (i = 0; i < cfg->line_outs; i++) {
2561 hda_nid_t dac = spec->multiout.dac_nids[i];
2564 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2567 err = add_control(spec, AD_CTL_WIDGET_VOL,
2568 "Center Playback Volume",
2569 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2572 err = add_control(spec, AD_CTL_WIDGET_VOL,
2573 "LFE Playback Volume",
2574 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2577 err = add_control(spec, AD_CTL_BIND_MUTE,
2578 "Center Playback Switch",
2579 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2582 err = add_control(spec, AD_CTL_BIND_MUTE,
2583 "LFE Playback Switch",
2584 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2588 sprintf(name, "%s Playback Volume", chname[i]);
2589 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2590 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2593 sprintf(name, "%s Playback Switch", chname[i]);
2594 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2595 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2603 /* add playback controls for speaker and HP outputs */
2604 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2607 struct ad198x_spec *spec = codec->spec;
2615 idx = ad1988_pin_idx(pin);
2616 nid = ad1988_idx_to_dac(codec, idx);
2617 /* specify the DAC as the extra output */
2618 if (! spec->multiout.hp_nid)
2619 spec->multiout.hp_nid = nid;
2621 spec->multiout.extra_out_nid[0] = nid;
2622 /* control HP volume/switch on the output mixer amp */
2623 sprintf(name, "%s Playback Volume", pfx);
2624 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2625 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2627 nid = ad1988_mixer_nids[idx];
2628 sprintf(name, "%s Playback Switch", pfx);
2629 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2630 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2635 /* create input playback/capture controls for the given pin */
2636 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2637 const char *ctlname, int boost)
2642 sprintf(name, "%s Playback Volume", ctlname);
2643 idx = ad1988_pin_to_loopback_idx(pin);
2644 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2645 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2647 sprintf(name, "%s Playback Switch", ctlname);
2648 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2649 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2653 idx = ad1988_pin_idx(pin);
2654 bnid = ad1988_boost_nids[idx];
2656 sprintf(name, "%s Boost", ctlname);
2657 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2658 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2665 /* create playback/capture controls for input pins */
2666 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2667 const struct auto_pin_cfg *cfg)
2669 struct hda_input_mux *imux = &spec->private_imux;
2672 for (i = 0; i < AUTO_PIN_LAST; i++) {
2673 err = new_analog_input(spec, cfg->input_pins[i],
2674 auto_pin_cfg_labels[i],
2675 i <= AUTO_PIN_FRONT_MIC);
2678 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2679 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2682 imux->items[imux->num_items].label = "Mix";
2683 imux->items[imux->num_items].index = 9;
2686 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2687 "Analog Mix Playback Volume",
2688 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2690 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2691 "Analog Mix Playback Switch",
2692 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2698 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2699 hda_nid_t nid, int pin_type,
2703 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2704 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2706 case 0x11: /* port-A - DAC 04 */
2707 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2709 case 0x14: /* port-B - DAC 06 */
2710 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2712 case 0x15: /* port-C - DAC 05 */
2713 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2715 case 0x17: /* port-E - DAC 0a */
2716 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2718 case 0x13: /* mono - DAC 04 */
2719 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2724 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2726 struct ad198x_spec *spec = codec->spec;
2729 for (i = 0; i < spec->autocfg.line_outs; i++) {
2730 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2731 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2735 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2737 struct ad198x_spec *spec = codec->spec;
2740 pin = spec->autocfg.speaker_pins[0];
2741 if (pin) /* connect to front */
2742 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2743 pin = spec->autocfg.hp_pins[0];
2744 if (pin) /* connect to front */
2745 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2748 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2750 struct ad198x_spec *spec = codec->spec;
2753 for (i = 0; i < AUTO_PIN_LAST; i++) {
2754 hda_nid_t nid = spec->autocfg.input_pins[i];
2758 case 0x15: /* port-C */
2759 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2761 case 0x17: /* port-E */
2762 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2765 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2766 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2767 if (nid != AD1988_PIN_CD_NID)
2768 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2770 idx = ad1988_pin_idx(nid);
2771 if (ad1988_boost_nids[idx])
2772 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2773 AC_VERB_SET_AMP_GAIN_MUTE,
2778 /* parse the BIOS configuration and set up the alc_spec */
2779 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2780 static int ad1988_parse_auto_config(struct hda_codec *codec)
2782 struct ad198x_spec *spec = codec->spec;
2785 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2787 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2789 if (! spec->autocfg.line_outs)
2790 return 0; /* can't find valid BIOS pin config */
2791 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2792 (err = ad1988_auto_create_extra_out(codec,
2793 spec->autocfg.speaker_pins[0],
2795 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2796 "Headphone")) < 0 ||
2797 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2800 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2802 if (spec->autocfg.dig_out_pin)
2803 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2804 if (spec->autocfg.dig_in_pin)
2805 spec->dig_in_nid = AD1988_SPDIF_IN;
2807 if (spec->kctl_alloc)
2808 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2810 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2812 spec->input_mux = &spec->private_imux;
2817 /* init callback for auto-configuration model -- overriding the default init */
2818 static int ad1988_auto_init(struct hda_codec *codec)
2821 ad1988_auto_init_multi_out(codec);
2822 ad1988_auto_init_extra_out(codec);
2823 ad1988_auto_init_analog_input(codec);
2831 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2832 [AD1988_6STACK] = "6stack",
2833 [AD1988_6STACK_DIG] = "6stack-dig",
2834 [AD1988_3STACK] = "3stack",
2835 [AD1988_3STACK_DIG] = "3stack-dig",
2836 [AD1988_LAPTOP] = "laptop",
2837 [AD1988_LAPTOP_DIG] = "laptop-dig",
2838 [AD1988_AUTO] = "auto",
2841 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2842 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2843 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2847 static int patch_ad1988(struct hda_codec *codec)
2849 struct ad198x_spec *spec;
2852 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2859 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2861 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2862 ad1988_models, ad1988_cfg_tbl);
2863 if (board_config < 0) {
2864 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2865 board_config = AD1988_AUTO;
2868 if (board_config == AD1988_AUTO) {
2869 /* automatic parse from the BIOS config */
2870 int err = ad1988_parse_auto_config(codec);
2875 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2876 board_config = AD1988_6STACK;
2880 switch (board_config) {
2882 case AD1988_6STACK_DIG:
2883 spec->multiout.max_channels = 8;
2884 spec->multiout.num_dacs = 4;
2886 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2888 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
2889 spec->input_mux = &ad1988_6stack_capture_source;
2890 spec->num_mixers = 2;
2892 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2894 spec->mixers[0] = ad1988_6stack_mixers1;
2895 spec->mixers[1] = ad1988_6stack_mixers2;
2896 spec->num_init_verbs = 1;
2897 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2898 if (board_config == AD1988_6STACK_DIG) {
2899 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2900 spec->dig_in_nid = AD1988_SPDIF_IN;
2904 case AD1988_3STACK_DIG:
2905 spec->multiout.max_channels = 6;
2906 spec->multiout.num_dacs = 3;
2908 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2910 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2911 spec->input_mux = &ad1988_6stack_capture_source;
2912 spec->channel_mode = ad1988_3stack_modes;
2913 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
2914 spec->num_mixers = 2;
2916 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
2918 spec->mixers[0] = ad1988_3stack_mixers1;
2919 spec->mixers[1] = ad1988_3stack_mixers2;
2920 spec->num_init_verbs = 1;
2921 spec->init_verbs[0] = ad1988_3stack_init_verbs;
2922 if (board_config == AD1988_3STACK_DIG)
2923 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2926 case AD1988_LAPTOP_DIG:
2927 spec->multiout.max_channels = 2;
2928 spec->multiout.num_dacs = 1;
2929 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2930 spec->input_mux = &ad1988_laptop_capture_source;
2931 spec->num_mixers = 1;
2932 spec->mixers[0] = ad1988_laptop_mixers;
2933 spec->num_init_verbs = 1;
2934 spec->init_verbs[0] = ad1988_laptop_init_verbs;
2935 if (board_config == AD1988_LAPTOP_DIG)
2936 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2940 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
2941 spec->adc_nids = ad1988_adc_nids;
2942 spec->capsrc_nids = ad1988_capsrc_nids;
2943 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
2944 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
2945 if (spec->multiout.dig_out_nid) {
2946 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
2947 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
2949 if (spec->dig_in_nid)
2950 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
2952 codec->patch_ops = ad198x_patch_ops;
2953 switch (board_config) {
2955 codec->patch_ops.init = ad1988_auto_init;
2958 case AD1988_LAPTOP_DIG:
2959 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
2962 #ifdef CONFIG_SND_HDA_POWER_SAVE
2963 spec->loopback.amplist = ad1988_loopbacks;
2965 spec->vmaster_nid = 0x04;
2974 * port-B - front line/mic-in
2975 * port-E - aux in/out
2976 * port-F - aux in/out
2977 * port-C - rear line/mic-in
2978 * port-D - rear line/hp-out
2979 * port-A - front line/hp-out
2981 * AD1984 = AD1884 + two digital mic-ins
2984 * For simplicity, we share the single DAC for both HP and line-outs
2985 * right now. The inidividual playbacks could be easily implemented,
2986 * but no build-up framework is given, so far.
2989 static hda_nid_t ad1884_dac_nids[1] = {
2993 static hda_nid_t ad1884_adc_nids[2] = {
2997 static hda_nid_t ad1884_capsrc_nids[2] = {
3001 #define AD1884_SPDIF_OUT 0x02
3003 static struct hda_input_mux ad1884_capture_source = {
3006 { "Front Mic", 0x0 },
3013 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3014 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3015 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3016 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3017 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3018 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3019 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3020 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3021 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3022 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3023 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3024 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3025 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3027 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3028 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3029 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
3030 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3032 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3033 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3034 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3035 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3036 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3037 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3039 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3040 /* The multiple "Capture Source" controls confuse alsamixer
3041 * So call somewhat different..
3043 /* .name = "Capture Source", */
3044 .name = "Input Source",
3046 .info = ad198x_mux_enum_info,
3047 .get = ad198x_mux_enum_get,
3048 .put = ad198x_mux_enum_put,
3050 /* SPDIF controls */
3051 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3053 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3054 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3055 /* identical with ad1983 */
3056 .info = ad1983_spdif_route_info,
3057 .get = ad1983_spdif_route_get,
3058 .put = ad1983_spdif_route_put,
3063 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3064 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3065 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3066 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3068 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3074 * initialization verbs
3076 static struct hda_verb ad1884_init_verbs[] = {
3077 /* DACs; mute as default */
3078 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3079 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3080 /* Port-A (HP) mixer */
3081 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3082 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3084 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3085 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3086 /* HP selector - select DAC2 */
3087 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3088 /* Port-D (Line-out) mixer */
3089 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3090 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3092 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3093 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3094 /* Mono-out mixer */
3095 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3096 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3098 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3099 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3101 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3102 /* Port-B (front mic) pin */
3103 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3104 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3105 /* Port-C (rear mic) pin */
3106 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3107 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3108 /* Analog mixer; mute as default */
3109 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3110 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3111 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3112 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3113 /* Analog Mix output amp */
3114 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3115 /* SPDIF output selector */
3116 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3117 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3121 #ifdef CONFIG_SND_HDA_POWER_SAVE
3122 static struct hda_amp_list ad1884_loopbacks[] = {
3123 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3124 { 0x20, HDA_INPUT, 1 }, /* Mic */
3125 { 0x20, HDA_INPUT, 2 }, /* CD */
3126 { 0x20, HDA_INPUT, 4 }, /* Docking */
3131 static const char *ad1884_slave_vols[] = {
3132 "PCM Playback Volume",
3133 "Mic Playback Volume",
3134 "Mono Playback Volume",
3135 "Front Mic Playback Volume",
3136 "Mic Playback Volume",
3137 "CD Playback Volume",
3138 "Internal Mic Playback Volume",
3139 "Docking Mic Playback Volume"
3140 "Beep Playback Volume",
3141 "IEC958 Playback Volume",
3145 static int patch_ad1884(struct hda_codec *codec)
3147 struct ad198x_spec *spec;
3149 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3153 mutex_init(&spec->amp_mutex);
3156 spec->multiout.max_channels = 2;
3157 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3158 spec->multiout.dac_nids = ad1884_dac_nids;
3159 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3160 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3161 spec->adc_nids = ad1884_adc_nids;
3162 spec->capsrc_nids = ad1884_capsrc_nids;
3163 spec->input_mux = &ad1884_capture_source;
3164 spec->num_mixers = 1;
3165 spec->mixers[0] = ad1884_base_mixers;
3166 spec->num_init_verbs = 1;
3167 spec->init_verbs[0] = ad1884_init_verbs;
3168 spec->spdif_route = 0;
3169 #ifdef CONFIG_SND_HDA_POWER_SAVE
3170 spec->loopback.amplist = ad1884_loopbacks;
3172 spec->vmaster_nid = 0x04;
3173 /* we need to cover all playback volumes */
3174 spec->slave_vols = ad1884_slave_vols;
3176 codec->patch_ops = ad198x_patch_ops;
3182 * Lenovo Thinkpad T61/X61
3184 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3188 { "Internal Mic", 0x1 },
3195 * Dell Precision T3400
3197 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3200 { "Front Mic", 0x0 },
3207 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3208 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3209 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3210 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3211 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3212 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3213 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3214 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3215 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3216 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3217 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3218 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3219 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3220 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3221 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3222 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3223 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3224 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3225 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3226 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3228 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3229 /* The multiple "Capture Source" controls confuse alsamixer
3230 * So call somewhat different..
3232 /* .name = "Capture Source", */
3233 .name = "Input Source",
3235 .info = ad198x_mux_enum_info,
3236 .get = ad198x_mux_enum_get,
3237 .put = ad198x_mux_enum_put,
3239 /* SPDIF controls */
3240 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3242 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3243 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3244 /* identical with ad1983 */
3245 .info = ad1983_spdif_route_info,
3246 .get = ad1983_spdif_route_get,
3247 .put = ad1983_spdif_route_put,
3252 /* additional verbs */
3253 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3254 /* Port-E (docking station mic) pin */
3255 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3256 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3257 /* docking mic boost */
3258 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3259 /* Analog mixer - docking mic; mute as default */
3260 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3261 /* enable EAPD bit */
3262 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3267 * Dell Precision T3400
3269 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3270 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3271 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3272 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3273 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3274 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3275 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3276 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3277 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3278 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3280 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3281 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3283 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3284 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3285 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3286 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3287 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3288 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3290 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3291 /* The multiple "Capture Source" controls confuse alsamixer
3292 * So call somewhat different..
3294 /* .name = "Capture Source", */
3295 .name = "Input Source",
3297 .info = ad198x_mux_enum_info,
3298 .get = ad198x_mux_enum_get,
3299 .put = ad198x_mux_enum_put,
3304 /* Digial MIC ADC NID 0x05 + 0x06 */
3305 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3306 struct hda_codec *codec,
3307 unsigned int stream_tag,
3308 unsigned int format,
3309 struct snd_pcm_substream *substream)
3311 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3312 stream_tag, 0, format);
3316 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3317 struct hda_codec *codec,
3318 struct snd_pcm_substream *substream)
3320 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3325 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3331 .prepare = ad1984_pcm_dmic_prepare,
3332 .cleanup = ad1984_pcm_dmic_cleanup
3336 static int ad1984_build_pcms(struct hda_codec *codec)
3338 struct ad198x_spec *spec = codec->spec;
3339 struct hda_pcm *info;
3342 err = ad198x_build_pcms(codec);
3346 info = spec->pcm_rec + codec->num_pcms;
3348 info->name = "AD1984 Digital Mic";
3349 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3357 AD1984_DELL_DESKTOP,
3361 static const char *ad1984_models[AD1984_MODELS] = {
3362 [AD1984_BASIC] = "basic",
3363 [AD1984_THINKPAD] = "thinkpad",
3364 [AD1984_DELL_DESKTOP] = "dell_desktop",
3367 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3368 /* Lenovo Thinkpad T61/X61 */
3369 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
3370 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3374 static int patch_ad1984(struct hda_codec *codec)
3376 struct ad198x_spec *spec;
3377 int board_config, err;
3379 err = patch_ad1884(codec);
3383 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3384 ad1984_models, ad1984_cfg_tbl);
3385 switch (board_config) {
3387 /* additional digital mics */
3388 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3389 codec->patch_ops.build_pcms = ad1984_build_pcms;
3391 case AD1984_THINKPAD:
3392 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3393 spec->input_mux = &ad1984_thinkpad_capture_source;
3394 spec->mixers[0] = ad1984_thinkpad_mixers;
3395 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3397 case AD1984_DELL_DESKTOP:
3398 spec->multiout.dig_out_nid = 0;
3399 spec->input_mux = &ad1984_dell_desktop_capture_source;
3400 spec->mixers[0] = ad1984_dell_desktop_mixers;
3410 * port-A - front hp-out
3411 * port-B - front mic-in
3412 * port-C - rear line-in, shared surr-out (3stack)
3413 * port-D - rear line-out
3414 * port-E - rear mic-in, shared clfe-out (3stack)
3415 * port-F - rear surr-out (6stack)
3416 * port-G - rear clfe-out (6stack)
3419 static hda_nid_t ad1882_dac_nids[3] = {
3423 static hda_nid_t ad1882_adc_nids[2] = {
3427 static hda_nid_t ad1882_capsrc_nids[2] = {
3431 #define AD1882_SPDIF_OUT 0x02
3433 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
3434 static struct hda_input_mux ad1882_capture_source = {
3437 { "Front Mic", 0x1 },
3445 static struct snd_kcontrol_new ad1882_base_mixers[] = {
3446 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3447 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
3448 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
3449 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
3450 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3451 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3452 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3453 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3454 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3455 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3456 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3457 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3458 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
3459 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
3460 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
3461 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
3462 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
3463 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
3464 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
3465 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
3466 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
3467 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3468 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3469 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3470 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3472 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3473 /* The multiple "Capture Source" controls confuse alsamixer
3474 * So call somewhat different..
3476 /* .name = "Capture Source", */
3477 .name = "Input Source",
3479 .info = ad198x_mux_enum_info,
3480 .get = ad198x_mux_enum_get,
3481 .put = ad198x_mux_enum_put,
3483 /* SPDIF controls */
3484 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3486 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3487 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3488 /* identical with ad1983 */
3489 .info = ad1983_spdif_route_info,
3490 .get = ad1983_spdif_route_get,
3491 .put = ad1983_spdif_route_put,
3496 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
3497 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3498 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
3499 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
3501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3502 .name = "Channel Mode",
3503 .info = ad198x_ch_mode_info,
3504 .get = ad198x_ch_mode_get,
3505 .put = ad198x_ch_mode_put,
3510 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
3511 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
3512 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
3513 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
3517 static struct hda_verb ad1882_ch2_init[] = {
3518 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3519 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3520 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3521 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3522 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3523 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3527 static struct hda_verb ad1882_ch4_init[] = {
3528 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3529 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3530 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3531 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3532 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3533 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3537 static struct hda_verb ad1882_ch6_init[] = {
3538 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3539 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3540 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3541 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3542 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3547 static struct hda_channel_mode ad1882_modes[3] = {
3548 { 2, ad1882_ch2_init },
3549 { 4, ad1882_ch4_init },
3550 { 6, ad1882_ch6_init },
3554 * initialization verbs
3556 static struct hda_verb ad1882_init_verbs[] = {
3557 /* DACs; mute as default */
3558 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3559 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3560 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3561 /* Port-A (HP) mixer */
3562 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3563 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3565 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3566 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3567 /* HP selector - select DAC2 */
3568 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
3569 /* Port-D (Line-out) mixer */
3570 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3571 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3573 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3574 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3575 /* Mono-out mixer */
3576 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3577 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3579 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3580 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3581 /* Port-B (front mic) pin */
3582 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3583 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3584 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3585 /* Port-C (line-in) pin */
3586 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3587 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3588 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3589 /* Port-C mixer - mute as input */
3590 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3591 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3592 /* Port-E (mic-in) pin */
3593 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3594 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3595 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3596 /* Port-E mixer - mute as input */
3597 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3598 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3599 /* Port-F (surround) */
3600 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3601 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3603 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3604 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3605 /* Analog mixer; mute as default */
3606 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
3607 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3608 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3609 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3610 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3611 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3612 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3613 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3614 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3615 /* Analog Mix output amp */
3616 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3617 /* SPDIF output selector */
3618 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3619 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3620 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3624 #ifdef CONFIG_SND_HDA_POWER_SAVE
3625 static struct hda_amp_list ad1882_loopbacks[] = {
3626 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3627 { 0x20, HDA_INPUT, 1 }, /* Mic */
3628 { 0x20, HDA_INPUT, 4 }, /* Line */
3629 { 0x20, HDA_INPUT, 6 }, /* CD */
3641 static const char *ad1882_models[AD1986A_MODELS] = {
3642 [AD1882_3STACK] = "3stack",
3643 [AD1882_6STACK] = "6stack",
3647 static int patch_ad1882(struct hda_codec *codec)
3649 struct ad198x_spec *spec;
3652 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3656 mutex_init(&spec->amp_mutex);
3659 spec->multiout.max_channels = 6;
3660 spec->multiout.num_dacs = 3;
3661 spec->multiout.dac_nids = ad1882_dac_nids;
3662 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
3663 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
3664 spec->adc_nids = ad1882_adc_nids;
3665 spec->capsrc_nids = ad1882_capsrc_nids;
3666 spec->input_mux = &ad1882_capture_source;
3667 spec->num_mixers = 1;
3668 spec->mixers[0] = ad1882_base_mixers;
3669 spec->num_init_verbs = 1;
3670 spec->init_verbs[0] = ad1882_init_verbs;
3671 spec->spdif_route = 0;
3672 #ifdef CONFIG_SND_HDA_POWER_SAVE
3673 spec->loopback.amplist = ad1882_loopbacks;
3675 spec->vmaster_nid = 0x04;
3677 codec->patch_ops = ad198x_patch_ops;
3679 /* override some parameters */
3680 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
3681 ad1882_models, NULL);
3682 switch (board_config) {
3685 spec->num_mixers = 2;
3686 spec->mixers[1] = ad1882_3stack_mixers;
3687 spec->channel_mode = ad1882_modes;
3688 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
3689 spec->need_dac_fix = 1;
3690 spec->multiout.max_channels = 2;
3691 spec->multiout.num_dacs = 1;
3694 spec->num_mixers = 2;
3695 spec->mixers[1] = ad1882_6stack_mixers;
3705 struct hda_codec_preset snd_hda_preset_analog[] = {
3706 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
3707 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
3708 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
3709 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
3710 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
3711 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
3712 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
3713 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },