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"
31 #include "hda_patch.h"
34 struct snd_kcontrol_new *mixers[5];
37 const struct hda_verb *init_verbs[5]; /* initialization verbs
38 * don't forget NULL termination!
40 unsigned int num_init_verbs;
43 struct hda_multi_out multiout; /* playback set-up
44 * max_channels, dacs must be set
45 * dig_out_nid and hp_nid are optional
47 unsigned int cur_eapd;
48 unsigned int need_dac_fix;
51 unsigned int num_adc_nids;
53 hda_nid_t dig_in_nid; /* digital-in NID; optional */
56 const struct hda_input_mux *input_mux;
57 hda_nid_t *capsrc_nids;
58 unsigned int cur_mux[3];
61 const struct hda_channel_mode *channel_mode;
65 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
67 struct mutex amp_mutex; /* PCM volume/mute control mutex */
68 unsigned int spdif_route;
70 /* dynamic controls, init_verbs and input_mux */
71 struct auto_pin_cfg autocfg;
72 unsigned int num_kctl_alloc, num_kctl_used;
73 struct snd_kcontrol_new *kctl_alloc;
74 struct hda_input_mux private_imux;
75 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
77 unsigned int jack_present :1;
79 #ifdef CONFIG_SND_HDA_POWER_SAVE
80 struct hda_loopback_check loopback;
82 /* for virtual master */
83 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);
174 err = snd_hda_create_spdif_share_sw(codec,
178 spec->multiout.share_spdif = 1;
180 if (spec->dig_in_nid) {
181 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
186 /* if we have no master control, let's create it */
187 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
188 unsigned int vmaster_tlv[4];
189 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
190 HDA_OUTPUT, vmaster_tlv);
191 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
194 spec->slave_vols : ad_slave_vols));
198 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
199 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
202 spec->slave_sws : ad_slave_sws));
210 #ifdef CONFIG_SND_HDA_POWER_SAVE
211 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
213 struct ad198x_spec *spec = codec->spec;
214 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
219 * Analog playback callbacks
221 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
222 struct hda_codec *codec,
223 struct snd_pcm_substream *substream)
225 struct ad198x_spec *spec = codec->spec;
226 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
230 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
231 struct hda_codec *codec,
232 unsigned int stream_tag,
234 struct snd_pcm_substream *substream)
236 struct ad198x_spec *spec = codec->spec;
237 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
241 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
242 struct hda_codec *codec,
243 struct snd_pcm_substream *substream)
245 struct ad198x_spec *spec = codec->spec;
246 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
252 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
253 struct hda_codec *codec,
254 struct snd_pcm_substream *substream)
256 struct ad198x_spec *spec = codec->spec;
257 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
260 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
261 struct hda_codec *codec,
262 struct snd_pcm_substream *substream)
264 struct ad198x_spec *spec = codec->spec;
265 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
268 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
269 struct hda_codec *codec,
270 unsigned int stream_tag,
272 struct snd_pcm_substream *substream)
274 struct ad198x_spec *spec = codec->spec;
275 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
282 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
283 struct hda_codec *codec,
284 unsigned int stream_tag,
286 struct snd_pcm_substream *substream)
288 struct ad198x_spec *spec = codec->spec;
289 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
290 stream_tag, 0, format);
294 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
295 struct hda_codec *codec,
296 struct snd_pcm_substream *substream)
298 struct ad198x_spec *spec = codec->spec;
299 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
307 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
310 .channels_max = 6, /* changed later */
311 .nid = 0, /* fill later */
313 .open = ad198x_playback_pcm_open,
314 .prepare = ad198x_playback_pcm_prepare,
315 .cleanup = ad198x_playback_pcm_cleanup
319 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
323 .nid = 0, /* fill later */
325 .prepare = ad198x_capture_pcm_prepare,
326 .cleanup = ad198x_capture_pcm_cleanup
330 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
334 .nid = 0, /* fill later */
336 .open = ad198x_dig_playback_pcm_open,
337 .close = ad198x_dig_playback_pcm_close,
338 .prepare = ad198x_dig_playback_pcm_prepare
342 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
346 /* NID is set in alc_build_pcms */
349 static int ad198x_build_pcms(struct hda_codec *codec)
351 struct ad198x_spec *spec = codec->spec;
352 struct hda_pcm *info = spec->pcm_rec;
355 codec->pcm_info = info;
357 info->name = "AD198x Analog";
358 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
359 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
360 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
361 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
362 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
363 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
365 if (spec->multiout.dig_out_nid) {
368 info->name = "AD198x Digital";
369 info->pcm_type = HDA_PCM_TYPE_SPDIF;
370 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
371 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
372 if (spec->dig_in_nid) {
373 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
374 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
381 static void ad198x_free(struct hda_codec *codec)
383 struct ad198x_spec *spec = codec->spec;
386 if (spec->kctl_alloc) {
387 for (i = 0; i < spec->num_kctl_used; i++)
388 kfree(spec->kctl_alloc[i].name);
389 kfree(spec->kctl_alloc);
394 static struct hda_codec_ops ad198x_patch_ops = {
395 .build_controls = ad198x_build_controls,
396 .build_pcms = ad198x_build_pcms,
399 #ifdef CONFIG_SND_HDA_POWER_SAVE
400 .check_power_status = ad198x_check_power_status,
407 * the private value = nid | (invert << 8)
409 #define ad198x_eapd_info snd_ctl_boolean_mono_info
411 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
414 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
415 struct ad198x_spec *spec = codec->spec;
416 int invert = (kcontrol->private_value >> 8) & 1;
418 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
420 ucontrol->value.integer.value[0] = spec->cur_eapd;
424 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
425 struct snd_ctl_elem_value *ucontrol)
427 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
428 struct ad198x_spec *spec = codec->spec;
429 int invert = (kcontrol->private_value >> 8) & 1;
430 hda_nid_t nid = kcontrol->private_value & 0xff;
432 eapd = !!ucontrol->value.integer.value[0];
435 if (eapd == spec->cur_eapd)
437 spec->cur_eapd = eapd;
438 snd_hda_codec_write_cache(codec, nid,
439 0, AC_VERB_SET_EAPD_BTLENABLE,
444 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
445 struct snd_ctl_elem_info *uinfo);
446 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
447 struct snd_ctl_elem_value *ucontrol);
448 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
449 struct snd_ctl_elem_value *ucontrol);
456 #define AD1986A_SPDIF_OUT 0x02
457 #define AD1986A_FRONT_DAC 0x03
458 #define AD1986A_SURR_DAC 0x04
459 #define AD1986A_CLFE_DAC 0x05
460 #define AD1986A_ADC 0x06
462 static hda_nid_t ad1986a_dac_nids[3] = {
463 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
465 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
466 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
468 static struct hda_input_mux ad1986a_capture_source = {
482 static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
483 .ops = &snd_hda_bind_vol,
485 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
486 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
487 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
492 static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
493 .ops = &snd_hda_bind_sw,
495 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
496 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
497 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
505 static struct snd_kcontrol_new ad1986a_mixers[] = {
507 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
509 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
510 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
511 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
512 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
513 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
514 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
515 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
516 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
517 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
518 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
519 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
520 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
521 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
522 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
523 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
524 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
525 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
526 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
527 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
528 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
529 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
530 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
531 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
532 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
533 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
534 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
535 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
537 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
538 .name = "Capture Source",
539 .info = ad198x_mux_enum_info,
540 .get = ad198x_mux_enum_get,
541 .put = ad198x_mux_enum_put,
543 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
547 /* additional mixers for 3stack mode */
548 static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
550 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
551 .name = "Channel Mode",
552 .info = ad198x_ch_mode_info,
553 .get = ad198x_ch_mode_get,
554 .put = ad198x_ch_mode_put,
559 /* laptop model - 2ch only */
560 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
562 /* master controls both pins 0x1a and 0x1b */
563 static struct hda_bind_ctls ad1986a_laptop_master_vol = {
564 .ops = &snd_hda_bind_vol,
566 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
567 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
572 static struct hda_bind_ctls ad1986a_laptop_master_sw = {
573 .ops = &snd_hda_bind_sw,
575 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
576 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
581 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
582 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
583 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
584 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
585 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
586 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
587 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
588 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
589 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
590 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
591 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
592 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
593 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
594 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
595 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
596 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
597 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
598 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
599 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
600 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
603 .name = "Capture Source",
604 .info = ad198x_mux_enum_info,
605 .get = ad198x_mux_enum_get,
606 .put = ad198x_mux_enum_put,
611 /* laptop-eapd model - 2ch only */
613 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
617 { "Internal Mic", 0x4 },
622 static struct hda_input_mux ad1986a_automic_capture_source = {
630 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
631 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
632 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
633 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
634 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
635 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
636 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
637 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
638 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
639 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
642 .name = "Capture Source",
643 .info = ad198x_mux_enum_info,
644 .get = ad198x_mux_enum_get,
645 .put = ad198x_mux_enum_put,
648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
649 .name = "External Amplifier",
650 .info = ad198x_eapd_info,
651 .get = ad198x_eapd_get,
652 .put = ad198x_eapd_put,
653 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
658 /* re-connect the mic boost input according to the jack sensing */
659 static void ad1986a_automic(struct hda_codec *codec)
661 unsigned int present;
662 present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
663 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
664 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
665 (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
668 #define AD1986A_MIC_EVENT 0x36
670 static void ad1986a_automic_unsol_event(struct hda_codec *codec,
673 if ((res >> 26) != AD1986A_MIC_EVENT)
675 ad1986a_automic(codec);
678 static int ad1986a_automic_init(struct hda_codec *codec)
681 ad1986a_automic(codec);
685 /* laptop-automute - 2ch only */
687 static void ad1986a_update_hp(struct hda_codec *codec)
689 struct ad198x_spec *spec = codec->spec;
692 if (spec->jack_present)
693 mute = HDA_AMP_MUTE; /* mute internal speaker */
695 /* unmute internal speaker if necessary */
696 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
697 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
701 static void ad1986a_hp_automute(struct hda_codec *codec)
703 struct ad198x_spec *spec = codec->spec;
704 unsigned int present;
706 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
707 /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
708 spec->jack_present = !(present & 0x80000000);
709 ad1986a_update_hp(codec);
712 #define AD1986A_HP_EVENT 0x37
714 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
716 if ((res >> 26) != AD1986A_HP_EVENT)
718 ad1986a_hp_automute(codec);
721 static int ad1986a_hp_init(struct hda_codec *codec)
724 ad1986a_hp_automute(codec);
728 /* bind hp and internal speaker mute (with plug check) */
729 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
730 struct snd_ctl_elem_value *ucontrol)
732 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
733 long *valp = ucontrol->value.integer.value;
736 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
738 valp[0] ? 0 : HDA_AMP_MUTE);
739 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
741 valp[1] ? 0 : HDA_AMP_MUTE);
743 ad1986a_update_hp(codec);
747 static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
748 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
751 .name = "Master Playback Switch",
752 .info = snd_hda_mixer_amp_switch_info,
753 .get = snd_hda_mixer_amp_switch_get,
754 .put = ad1986a_hp_master_sw_put,
755 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
757 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
758 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
759 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
760 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
761 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
762 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
763 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
764 HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
765 HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
766 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
767 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
770 .name = "Capture Source",
771 .info = ad198x_mux_enum_info,
772 .get = ad198x_mux_enum_get,
773 .put = ad198x_mux_enum_put,
776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
777 .name = "External Amplifier",
778 .info = ad198x_eapd_info,
779 .get = ad198x_eapd_get,
780 .put = ad198x_eapd_put,
781 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
787 * initialization verbs
789 static struct hda_verb ad1986a_init_verbs[] = {
790 /* Front, Surround, CLFE DAC; mute as default */
791 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
792 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
793 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
795 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
796 /* HP, Line-Out, Surround, CLFE selectors */
797 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
798 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
799 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
800 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
802 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
803 /* Mic selector: Mic 1/2 pin */
804 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
805 /* Line-in selector: Line-in */
806 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
808 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
809 /* Record selector: mic */
810 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
811 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
812 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
813 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
814 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
815 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
816 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
818 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
819 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
820 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
821 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
822 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
823 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
824 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
826 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
827 /* Front, Surround, CLFE Pins */
828 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
829 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
830 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
832 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
834 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
835 /* Line, Aux, CD, Beep-In Pin */
836 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
837 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
838 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
839 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
840 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
844 static struct hda_verb ad1986a_ch2_init[] = {
845 /* Surround out -> Line In */
846 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
847 /* Line-in selectors */
848 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
850 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
851 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
852 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
856 static struct hda_verb ad1986a_ch4_init[] = {
857 /* Surround out -> Surround */
858 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
859 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
861 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
862 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
866 static struct hda_verb ad1986a_ch6_init[] = {
867 /* Surround out -> Surround out */
868 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
869 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
871 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
872 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
876 static struct hda_channel_mode ad1986a_modes[3] = {
877 { 2, ad1986a_ch2_init },
878 { 4, ad1986a_ch4_init },
879 { 6, ad1986a_ch6_init },
882 /* eapd initialization */
883 static struct hda_verb ad1986a_eapd_init_verbs[] = {
884 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
888 static struct hda_verb ad1986a_automic_verbs[] = {
889 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
890 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
891 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
892 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
893 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
897 /* Ultra initialization */
898 static struct hda_verb ad1986a_ultra_init[] = {
899 /* eapd initialization */
900 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
902 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
903 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
904 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
908 /* pin sensing on HP jack */
909 static struct hda_verb ad1986a_hp_init_verbs[] = {
910 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
921 AD1986A_LAPTOP_AUTOMUTE,
926 static const char *ad1986a_models[AD1986A_MODELS] = {
927 [AD1986A_6STACK] = "6stack",
928 [AD1986A_3STACK] = "3stack",
929 [AD1986A_LAPTOP] = "laptop",
930 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
931 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
932 [AD1986A_ULTRA] = "ultra",
935 static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
936 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
937 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
938 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
939 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
940 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
941 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
942 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
943 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
944 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
945 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
946 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
947 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
948 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
949 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
950 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
951 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
952 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
953 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
954 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
955 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
956 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
957 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
958 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
959 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
960 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
961 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
962 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
963 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
967 #ifdef CONFIG_SND_HDA_POWER_SAVE
968 static struct hda_amp_list ad1986a_loopbacks[] = {
969 { 0x13, HDA_OUTPUT, 0 }, /* Mic */
970 { 0x14, HDA_OUTPUT, 0 }, /* Phone */
971 { 0x15, HDA_OUTPUT, 0 }, /* CD */
972 { 0x16, HDA_OUTPUT, 0 }, /* Aux */
973 { 0x17, HDA_OUTPUT, 0 }, /* Line */
978 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
980 unsigned int conf = snd_hda_codec_read(codec, nid, 0,
981 AC_VERB_GET_CONFIG_DEFAULT, 0);
982 return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
985 static int patch_ad1986a(struct hda_codec *codec)
987 struct ad198x_spec *spec;
990 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
996 spec->multiout.max_channels = 6;
997 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
998 spec->multiout.dac_nids = ad1986a_dac_nids;
999 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1000 spec->num_adc_nids = 1;
1001 spec->adc_nids = ad1986a_adc_nids;
1002 spec->capsrc_nids = ad1986a_capsrc_nids;
1003 spec->input_mux = &ad1986a_capture_source;
1004 spec->num_mixers = 1;
1005 spec->mixers[0] = ad1986a_mixers;
1006 spec->num_init_verbs = 1;
1007 spec->init_verbs[0] = ad1986a_init_verbs;
1008 #ifdef CONFIG_SND_HDA_POWER_SAVE
1009 spec->loopback.amplist = ad1986a_loopbacks;
1011 spec->vmaster_nid = 0x1b;
1013 codec->patch_ops = ad198x_patch_ops;
1015 /* override some parameters */
1016 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1019 switch (board_config) {
1020 case AD1986A_3STACK:
1021 spec->num_mixers = 2;
1022 spec->mixers[1] = ad1986a_3st_mixers;
1023 spec->num_init_verbs = 2;
1024 spec->init_verbs[1] = ad1986a_ch2_init;
1025 spec->channel_mode = ad1986a_modes;
1026 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1027 spec->need_dac_fix = 1;
1028 spec->multiout.max_channels = 2;
1029 spec->multiout.num_dacs = 1;
1031 case AD1986A_LAPTOP:
1032 spec->mixers[0] = ad1986a_laptop_mixers;
1033 spec->multiout.max_channels = 2;
1034 spec->multiout.num_dacs = 1;
1035 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1037 case AD1986A_LAPTOP_EAPD:
1038 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1039 spec->num_init_verbs = 3;
1040 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1041 spec->init_verbs[2] = ad1986a_automic_verbs;
1042 spec->multiout.max_channels = 2;
1043 spec->multiout.num_dacs = 1;
1044 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1045 if (!is_jack_available(codec, 0x25))
1046 spec->multiout.dig_out_nid = 0;
1047 spec->input_mux = &ad1986a_automic_capture_source;
1048 codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1049 codec->patch_ops.init = ad1986a_automic_init;
1051 case AD1986A_LAPTOP_AUTOMUTE:
1052 spec->mixers[0] = ad1986a_laptop_automute_mixers;
1053 spec->num_init_verbs = 3;
1054 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1055 spec->init_verbs[2] = ad1986a_hp_init_verbs;
1056 spec->multiout.max_channels = 2;
1057 spec->multiout.num_dacs = 1;
1058 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1059 if (!is_jack_available(codec, 0x25))
1060 spec->multiout.dig_out_nid = 0;
1061 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1062 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1063 codec->patch_ops.init = ad1986a_hp_init;
1066 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1067 spec->num_init_verbs = 2;
1068 spec->init_verbs[1] = ad1986a_ultra_init;
1069 spec->multiout.max_channels = 2;
1070 spec->multiout.num_dacs = 1;
1071 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1072 spec->multiout.dig_out_nid = 0;
1076 /* AD1986A has a hardware problem that it can't share a stream
1077 * with multiple output pins. The copy of front to surrounds
1078 * causes noisy or silent outputs at a certain timing, e.g.
1079 * changing the volume.
1080 * So, let's disable the shared stream.
1082 spec->multiout.no_share_stream = 1;
1091 #define AD1983_SPDIF_OUT 0x02
1092 #define AD1983_DAC 0x03
1093 #define AD1983_ADC 0x04
1095 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1096 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1097 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1099 static struct hda_input_mux ad1983_capture_source = {
1105 { "Mix Mono", 0x3 },
1110 * SPDIF playback route
1112 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1114 static char *texts[] = { "PCM", "ADC" };
1116 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1118 uinfo->value.enumerated.items = 2;
1119 if (uinfo->value.enumerated.item > 1)
1120 uinfo->value.enumerated.item = 1;
1121 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1125 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1127 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1128 struct ad198x_spec *spec = codec->spec;
1130 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1134 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1136 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1137 struct ad198x_spec *spec = codec->spec;
1139 if (ucontrol->value.enumerated.item[0] > 1)
1141 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1142 spec->spdif_route = ucontrol->value.enumerated.item[0];
1143 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1144 AC_VERB_SET_CONNECT_SEL,
1151 static struct snd_kcontrol_new ad1983_mixers[] = {
1152 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1153 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1154 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1155 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1156 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1157 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1158 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1159 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1160 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1161 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1162 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1163 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1164 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
1165 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
1166 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1167 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1168 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1170 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1171 .name = "Capture Source",
1172 .info = ad198x_mux_enum_info,
1173 .get = ad198x_mux_enum_get,
1174 .put = ad198x_mux_enum_put,
1177 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1178 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1179 .info = ad1983_spdif_route_info,
1180 .get = ad1983_spdif_route_get,
1181 .put = ad1983_spdif_route_put,
1186 static struct hda_verb ad1983_init_verbs[] = {
1187 /* Front, HP, Mono; mute as default */
1188 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1189 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1190 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1191 /* Beep, PCM, Mic, Line-In: mute */
1192 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1193 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1194 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1195 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1196 /* Front, HP selectors; from Mix */
1197 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1198 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1199 /* Mono selector; from Mix */
1200 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1201 /* Mic selector; Mic */
1202 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1203 /* Line-in selector: Line-in */
1204 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1205 /* Mic boost: 0dB */
1206 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1207 /* Record selector: mic */
1208 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1209 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1210 /* SPDIF route: PCM */
1211 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1213 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1215 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1217 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1219 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1221 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1225 #ifdef CONFIG_SND_HDA_POWER_SAVE
1226 static struct hda_amp_list ad1983_loopbacks[] = {
1227 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1228 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1233 static int patch_ad1983(struct hda_codec *codec)
1235 struct ad198x_spec *spec;
1237 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1243 spec->multiout.max_channels = 2;
1244 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1245 spec->multiout.dac_nids = ad1983_dac_nids;
1246 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1247 spec->num_adc_nids = 1;
1248 spec->adc_nids = ad1983_adc_nids;
1249 spec->capsrc_nids = ad1983_capsrc_nids;
1250 spec->input_mux = &ad1983_capture_source;
1251 spec->num_mixers = 1;
1252 spec->mixers[0] = ad1983_mixers;
1253 spec->num_init_verbs = 1;
1254 spec->init_verbs[0] = ad1983_init_verbs;
1255 spec->spdif_route = 0;
1256 #ifdef CONFIG_SND_HDA_POWER_SAVE
1257 spec->loopback.amplist = ad1983_loopbacks;
1259 spec->vmaster_nid = 0x05;
1261 codec->patch_ops = ad198x_patch_ops;
1268 * AD1981 HD specific
1271 #define AD1981_SPDIF_OUT 0x02
1272 #define AD1981_DAC 0x03
1273 #define AD1981_ADC 0x04
1275 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1276 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1277 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1279 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1280 static struct hda_input_mux ad1981_capture_source = {
1283 { "Front Mic", 0x0 },
1286 { "Mix Mono", 0x3 },
1293 static struct snd_kcontrol_new ad1981_mixers[] = {
1294 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1295 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1296 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1297 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1298 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1299 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1300 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1301 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1302 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1303 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1304 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1305 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1306 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1307 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1308 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1309 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1310 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1311 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1312 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
1313 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
1314 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1315 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1316 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1317 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1319 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1320 .name = "Capture Source",
1321 .info = ad198x_mux_enum_info,
1322 .get = ad198x_mux_enum_get,
1323 .put = ad198x_mux_enum_put,
1325 /* identical with AD1983 */
1327 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1328 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1329 .info = ad1983_spdif_route_info,
1330 .get = ad1983_spdif_route_get,
1331 .put = ad1983_spdif_route_put,
1336 static struct hda_verb ad1981_init_verbs[] = {
1337 /* Front, HP, Mono; mute as default */
1338 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1339 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1340 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1341 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1342 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1343 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1344 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1345 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1346 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1347 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1348 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1349 /* Front, HP selectors; from Mix */
1350 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1351 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1352 /* Mono selector; from Mix */
1353 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1354 /* Mic Mixer; select Front Mic */
1355 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1356 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1357 /* Mic boost: 0dB */
1358 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1359 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1360 /* Record selector: Front mic */
1361 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1362 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1363 /* SPDIF route: PCM */
1364 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1366 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1368 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1370 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1371 /* Front & Rear Mic Pins */
1372 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1373 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1375 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1377 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1378 /* Line-Out as Input: disabled */
1379 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1383 #ifdef CONFIG_SND_HDA_POWER_SAVE
1384 static struct hda_amp_list ad1981_loopbacks[] = {
1385 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1386 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1387 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1388 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1389 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1395 * Patch for HP nx6320
1397 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1398 * speaker output enabled _and_ mute-LED off.
1401 #define AD1981_HP_EVENT 0x37
1402 #define AD1981_MIC_EVENT 0x38
1404 static struct hda_verb ad1981_hp_init_verbs[] = {
1405 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1406 /* pin sensing on HP and Mic jacks */
1407 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1408 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1412 /* turn on/off EAPD (+ mute HP) as a master switch */
1413 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1414 struct snd_ctl_elem_value *ucontrol)
1416 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1417 struct ad198x_spec *spec = codec->spec;
1419 if (! ad198x_eapd_put(kcontrol, ucontrol))
1421 /* change speaker pin appropriately */
1422 snd_hda_codec_write(codec, 0x05, 0,
1423 AC_VERB_SET_PIN_WIDGET_CONTROL,
1424 spec->cur_eapd ? PIN_OUT : 0);
1425 /* toggle HP mute appropriately */
1426 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1428 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1432 /* bind volumes of both NID 0x05 and 0x06 */
1433 static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1434 .ops = &snd_hda_bind_vol,
1436 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1437 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1442 /* mute internal speaker if HP is plugged */
1443 static void ad1981_hp_automute(struct hda_codec *codec)
1445 unsigned int present;
1447 present = snd_hda_codec_read(codec, 0x06, 0,
1448 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1449 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1450 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1453 /* toggle input of built-in and mic jack appropriately */
1454 static void ad1981_hp_automic(struct hda_codec *codec)
1456 static struct hda_verb mic_jack_on[] = {
1457 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1458 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1461 static struct hda_verb mic_jack_off[] = {
1462 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1463 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1466 unsigned int present;
1468 present = snd_hda_codec_read(codec, 0x08, 0,
1469 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1471 snd_hda_sequence_write(codec, mic_jack_on);
1473 snd_hda_sequence_write(codec, mic_jack_off);
1476 /* unsolicited event for HP jack sensing */
1477 static void ad1981_hp_unsol_event(struct hda_codec *codec,
1482 case AD1981_HP_EVENT:
1483 ad1981_hp_automute(codec);
1485 case AD1981_MIC_EVENT:
1486 ad1981_hp_automic(codec);
1491 static struct hda_input_mux ad1981_hp_capture_source = {
1495 { "Docking-Station", 0x1 },
1500 static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1501 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1503 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1504 .name = "Master Playback Switch",
1505 .info = ad198x_eapd_info,
1506 .get = ad198x_eapd_get,
1507 .put = ad1981_hp_master_sw_put,
1508 .private_value = 0x05,
1510 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1513 /* FIXME: analog mic/line loopback doesn't work with my tests...
1514 * (although recording is OK)
1516 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1517 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1518 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1519 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1520 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1521 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1522 /* FIXME: does this laptop have analog CD connection? */
1523 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1524 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1526 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1527 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1528 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1529 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1532 .name = "Capture Source",
1533 .info = ad198x_mux_enum_info,
1534 .get = ad198x_mux_enum_get,
1535 .put = ad198x_mux_enum_put,
1540 /* initialize jack-sensing, too */
1541 static int ad1981_hp_init(struct hda_codec *codec)
1544 ad1981_hp_automute(codec);
1545 ad1981_hp_automic(codec);
1549 /* configuration for Toshiba Laptops */
1550 static struct hda_verb ad1981_toshiba_init_verbs[] = {
1551 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1552 /* pin sensing on HP and Mic jacks */
1553 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1554 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1558 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1559 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1560 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1564 /* configuration for Lenovo Thinkpad T60 */
1565 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1566 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1567 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1568 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1569 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1570 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1571 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1572 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1573 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1574 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1575 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1576 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1578 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1579 .name = "Capture Source",
1580 .info = ad198x_mux_enum_info,
1581 .get = ad198x_mux_enum_get,
1582 .put = ad198x_mux_enum_put,
1584 /* identical with AD1983 */
1586 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1587 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1588 .info = ad1983_spdif_route_info,
1589 .get = ad1983_spdif_route_get,
1590 .put = ad1983_spdif_route_put,
1595 static struct hda_input_mux ad1981_thinkpad_capture_source = {
1613 static const char *ad1981_models[AD1981_MODELS] = {
1615 [AD1981_THINKPAD] = "thinkpad",
1616 [AD1981_BASIC] = "basic",
1617 [AD1981_TOSHIBA] = "toshiba"
1620 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1621 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1623 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
1624 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1625 /* Lenovo Thinkpad T60/X60/Z6xx */
1626 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
1627 /* HP nx6320 (reversed SSID, H/W bug) */
1628 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1632 static int patch_ad1981(struct hda_codec *codec)
1634 struct ad198x_spec *spec;
1637 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1643 spec->multiout.max_channels = 2;
1644 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1645 spec->multiout.dac_nids = ad1981_dac_nids;
1646 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1647 spec->num_adc_nids = 1;
1648 spec->adc_nids = ad1981_adc_nids;
1649 spec->capsrc_nids = ad1981_capsrc_nids;
1650 spec->input_mux = &ad1981_capture_source;
1651 spec->num_mixers = 1;
1652 spec->mixers[0] = ad1981_mixers;
1653 spec->num_init_verbs = 1;
1654 spec->init_verbs[0] = ad1981_init_verbs;
1655 spec->spdif_route = 0;
1656 #ifdef CONFIG_SND_HDA_POWER_SAVE
1657 spec->loopback.amplist = ad1981_loopbacks;
1659 spec->vmaster_nid = 0x05;
1661 codec->patch_ops = ad198x_patch_ops;
1663 /* override some parameters */
1664 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1667 switch (board_config) {
1669 spec->mixers[0] = ad1981_hp_mixers;
1670 spec->num_init_verbs = 2;
1671 spec->init_verbs[1] = ad1981_hp_init_verbs;
1672 spec->multiout.dig_out_nid = 0;
1673 spec->input_mux = &ad1981_hp_capture_source;
1675 codec->patch_ops.init = ad1981_hp_init;
1676 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1678 case AD1981_THINKPAD:
1679 spec->mixers[0] = ad1981_thinkpad_mixers;
1680 spec->input_mux = &ad1981_thinkpad_capture_source;
1682 case AD1981_TOSHIBA:
1683 spec->mixers[0] = ad1981_hp_mixers;
1684 spec->mixers[1] = ad1981_toshiba_mixers;
1685 spec->num_init_verbs = 2;
1686 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1687 spec->multiout.dig_out_nid = 0;
1688 spec->input_mux = &ad1981_hp_capture_source;
1689 codec->patch_ops.init = ad1981_hp_init;
1690 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1700 * Output pins and routes
1702 * Pin Mix Sel DAC (*)
1703 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1704 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1705 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1706 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1707 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1708 * port-F 0x16 (mute) <- 0x2a <- 06
1709 * port-G 0x24 (mute) <- 0x27 <- 05
1710 * port-H 0x25 (mute) <- 0x28 <- 0a
1711 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1713 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1714 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1716 * Input pins and routes
1718 * pin boost mix input # / adc input #
1719 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1720 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1721 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1722 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1723 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1724 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1725 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1726 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1730 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1731 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1733 * Inputs of Analog Mix (0x20)
1734 * 0:Port-B (front mic)
1735 * 1:Port-C/G/H (line-in)
1737 * 3:Port-D (line-in/2)
1738 * 4:Port-E/G/H (mic-in)
1739 * 5:Port-F (mic2-in)
1745 * 1:Port-B (front mic-in)
1746 * 2:Port-C (line-in)
1747 * 3:Port-F (mic2-in)
1752 * 8:Port-D (line-in/2)
1755 * Proposed pin assignments by the datasheet
1758 * Port-A front headphone
1768 * Port-A front headphone
1770 * C rear line-in/surround
1772 * E rear mic-in/CLFE
1778 * D internal speaker (with EAPD)
1779 * E/F quad mic array
1795 /* reivision id to check workarounds */
1796 #define AD1988A_REV2 0x100200
1798 #define is_rev2(codec) \
1799 ((codec)->vendor_id == 0x11d41988 && \
1800 (codec)->revision_id == AD1988A_REV2)
1806 static hda_nid_t ad1988_6stack_dac_nids[4] = {
1807 0x04, 0x06, 0x05, 0x0a
1810 static hda_nid_t ad1988_3stack_dac_nids[3] = {
1814 /* for AD1988A revision-2, DAC2-4 are swapped */
1815 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
1816 0x04, 0x05, 0x0a, 0x06
1819 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
1823 static hda_nid_t ad1988_adc_nids[3] = {
1827 static hda_nid_t ad1988_capsrc_nids[3] = {
1831 #define AD1988_SPDIF_OUT 0x02
1832 #define AD1988_SPDIF_IN 0x07
1834 static struct hda_input_mux ad1988_6stack_capture_source = {
1837 { "Front Mic", 0x1 }, /* port-B */
1838 { "Line", 0x2 }, /* port-C */
1839 { "Mic", 0x4 }, /* port-E */
1845 static struct hda_input_mux ad1988_laptop_capture_source = {
1848 { "Mic/Line", 0x1 }, /* port-B */
1856 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
1857 struct snd_ctl_elem_info *uinfo)
1859 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1860 struct ad198x_spec *spec = codec->spec;
1861 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1862 spec->num_channel_mode);
1865 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1866 struct snd_ctl_elem_value *ucontrol)
1868 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1869 struct ad198x_spec *spec = codec->spec;
1870 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1871 spec->num_channel_mode, spec->multiout.max_channels);
1874 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1875 struct snd_ctl_elem_value *ucontrol)
1877 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1878 struct ad198x_spec *spec = codec->spec;
1879 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1880 spec->num_channel_mode,
1881 &spec->multiout.max_channels);
1882 if (err >= 0 && spec->need_dac_fix)
1883 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1888 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1889 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1890 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1891 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1892 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1893 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1897 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
1898 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1899 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1900 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1901 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
1902 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1906 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
1907 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1908 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1909 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1910 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1911 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1912 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1913 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1915 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1916 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1917 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1918 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1919 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1920 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1921 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1922 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1924 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1925 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1927 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1928 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1930 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1931 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1937 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
1938 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1939 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1940 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1941 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1945 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
1946 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1947 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1948 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
1949 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
1953 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
1954 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1955 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
1956 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
1957 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
1958 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1959 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1961 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1962 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1963 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1964 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1965 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1966 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1967 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1968 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1970 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1971 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1973 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
1974 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1976 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1977 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1979 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1980 .name = "Channel Mode",
1981 .info = ad198x_ch_mode_info,
1982 .get = ad198x_ch_mode_get,
1983 .put = ad198x_ch_mode_put,
1990 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1991 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1992 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1993 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1995 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1996 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1997 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1998 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1999 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2000 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2002 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
2003 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2005 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2006 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2008 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2011 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2012 .name = "External Amplifier",
2013 .info = ad198x_eapd_info,
2014 .get = ad198x_eapd_get,
2015 .put = ad198x_eapd_put,
2016 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
2023 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2024 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2025 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2026 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2027 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2028 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2029 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2031 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2032 /* The multiple "Capture Source" controls confuse alsamixer
2033 * So call somewhat different..
2035 /* .name = "Capture Source", */
2036 .name = "Input Source",
2038 .info = ad198x_mux_enum_info,
2039 .get = ad198x_mux_enum_get,
2040 .put = ad198x_mux_enum_put,
2045 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2046 struct snd_ctl_elem_info *uinfo)
2048 static char *texts[] = {
2049 "PCM", "ADC1", "ADC2", "ADC3"
2051 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2053 uinfo->value.enumerated.items = 4;
2054 if (uinfo->value.enumerated.item >= 4)
2055 uinfo->value.enumerated.item = 3;
2056 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2060 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2061 struct snd_ctl_elem_value *ucontrol)
2063 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2066 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2069 ucontrol->value.enumerated.item[0] = 0;
2071 sel = snd_hda_codec_read(codec, 0x0b, 0,
2072 AC_VERB_GET_CONNECT_SEL, 0);
2077 ucontrol->value.enumerated.item[0] = sel;
2082 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2083 struct snd_ctl_elem_value *ucontrol)
2085 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2086 unsigned int val, sel;
2089 val = ucontrol->value.enumerated.item[0];
2093 sel = snd_hda_codec_read(codec, 0x1d, 0,
2094 AC_VERB_GET_AMP_GAIN_MUTE,
2096 change = sel & 0x80;
2098 snd_hda_codec_write_cache(codec, 0x1d, 0,
2099 AC_VERB_SET_AMP_GAIN_MUTE,
2101 snd_hda_codec_write_cache(codec, 0x1d, 0,
2102 AC_VERB_SET_AMP_GAIN_MUTE,
2106 sel = snd_hda_codec_read(codec, 0x1d, 0,
2107 AC_VERB_GET_AMP_GAIN_MUTE,
2108 AC_AMP_GET_INPUT | 0x01);
2109 change = sel & 0x80;
2111 snd_hda_codec_write_cache(codec, 0x1d, 0,
2112 AC_VERB_SET_AMP_GAIN_MUTE,
2114 snd_hda_codec_write_cache(codec, 0x1d, 0,
2115 AC_VERB_SET_AMP_GAIN_MUTE,
2118 sel = snd_hda_codec_read(codec, 0x0b, 0,
2119 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2120 change |= sel != val;
2122 snd_hda_codec_write_cache(codec, 0x0b, 0,
2123 AC_VERB_SET_CONNECT_SEL,
2129 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2130 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2132 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2133 .name = "IEC958 Playback Source",
2134 .info = ad1988_spdif_playback_source_info,
2135 .get = ad1988_spdif_playback_source_get,
2136 .put = ad1988_spdif_playback_source_put,
2141 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2142 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2148 * initialization verbs
2152 * for 6-stack (+dig)
2154 static struct hda_verb ad1988_6stack_init_verbs[] = {
2155 /* Front, Surround, CLFE, side DAC; unmute as default */
2156 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2157 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2158 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2159 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2160 /* Port-A front headphon path */
2161 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2162 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2163 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2164 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2165 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2166 /* Port-D line-out path */
2167 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2168 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2169 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2170 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2171 /* Port-F surround path */
2172 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2173 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2174 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2175 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2176 /* Port-G CLFE path */
2177 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2178 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2179 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2180 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2181 /* Port-H side path */
2182 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2183 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2184 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2185 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2187 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2188 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2189 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2190 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2191 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2192 /* Port-B front mic-in path */
2193 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2194 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2195 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2196 /* Port-C line-in path */
2197 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2198 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2199 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2200 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2201 /* Port-E mic-in path */
2202 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2203 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2204 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2205 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2206 /* Analog CD Input */
2207 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2212 static struct hda_verb ad1988_capture_init_verbs[] = {
2213 /* mute analog mix */
2214 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2215 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2216 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2217 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2218 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2219 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2220 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2221 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2222 /* select ADCs - front-mic */
2223 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2224 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2225 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2227 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2228 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2229 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2234 static struct hda_verb ad1988_spdif_init_verbs[] = {
2236 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2237 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2238 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2239 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2241 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2247 * verbs for 3stack (+dig)
2249 static struct hda_verb ad1988_3stack_ch2_init[] = {
2250 /* set port-C to line-in */
2251 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2252 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2253 /* set port-E to mic-in */
2254 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2255 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2259 static struct hda_verb ad1988_3stack_ch6_init[] = {
2260 /* set port-C to surround out */
2261 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2262 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2263 /* set port-E to CLFE out */
2264 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2265 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2269 static struct hda_channel_mode ad1988_3stack_modes[2] = {
2270 { 2, ad1988_3stack_ch2_init },
2271 { 6, ad1988_3stack_ch6_init },
2274 static struct hda_verb ad1988_3stack_init_verbs[] = {
2275 /* Front, Surround, CLFE, side DAC; unmute as default */
2276 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2277 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2278 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2279 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2280 /* Port-A front headphon path */
2281 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2282 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2283 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2284 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2285 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2286 /* Port-D line-out path */
2287 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2288 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2289 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2290 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2292 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2293 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2294 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2295 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2296 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2297 /* Port-B front mic-in path */
2298 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2299 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2300 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2301 /* Port-C line-in/surround path - 6ch mode as default */
2302 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2303 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2304 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2305 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2306 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2307 /* Port-E mic-in/CLFE path - 6ch mode as default */
2308 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2309 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2310 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2311 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2312 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2313 /* mute analog mix */
2314 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2315 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2316 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2317 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2318 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2319 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2320 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2321 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2322 /* select ADCs - front-mic */
2323 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2324 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2325 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2327 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2328 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2329 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2334 * verbs for laptop mode (+dig)
2336 static struct hda_verb ad1988_laptop_hp_on[] = {
2337 /* unmute port-A and mute port-D */
2338 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2339 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2342 static struct hda_verb ad1988_laptop_hp_off[] = {
2343 /* mute port-A and unmute port-D */
2344 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2345 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2349 #define AD1988_HP_EVENT 0x01
2351 static struct hda_verb ad1988_laptop_init_verbs[] = {
2352 /* Front, Surround, CLFE, side DAC; unmute as default */
2353 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2354 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2355 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2356 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2357 /* Port-A front headphon path */
2358 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2359 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2360 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2361 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2362 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2363 /* unsolicited event for pin-sense */
2364 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2365 /* Port-D line-out path + EAPD */
2366 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2367 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2368 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2369 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2370 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2372 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2373 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2374 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2375 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2376 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2377 /* Port-B mic-in path */
2378 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2379 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2380 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2381 /* Port-C docking station - try to output */
2382 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2383 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2384 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2385 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2386 /* mute analog mix */
2387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2388 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2389 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2390 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2391 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2392 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2393 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2394 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2395 /* select ADCs - mic */
2396 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2397 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2398 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2400 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2401 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2402 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2406 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2408 if ((res >> 26) != AD1988_HP_EVENT)
2410 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
2411 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2413 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2416 #ifdef CONFIG_SND_HDA_POWER_SAVE
2417 static struct hda_amp_list ad1988_loopbacks[] = {
2418 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2419 { 0x20, HDA_INPUT, 1 }, /* Line */
2420 { 0x20, HDA_INPUT, 4 }, /* Mic */
2421 { 0x20, HDA_INPUT, 6 }, /* CD */
2427 * Automatic parse of I/O pins from the BIOS configuration
2430 #define NUM_CONTROL_ALLOC 32
2431 #define NUM_VERB_ALLOC 32
2438 static struct snd_kcontrol_new ad1988_control_templates[] = {
2439 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2440 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2441 HDA_BIND_MUTE(NULL, 0, 0, 0),
2444 /* add dynamic controls */
2445 static int add_control(struct ad198x_spec *spec, int type, const char *name,
2448 struct snd_kcontrol_new *knew;
2450 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
2451 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
2453 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
2456 if (spec->kctl_alloc) {
2457 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2458 kfree(spec->kctl_alloc);
2460 spec->kctl_alloc = knew;
2461 spec->num_kctl_alloc = num;
2464 knew = &spec->kctl_alloc[spec->num_kctl_used];
2465 *knew = ad1988_control_templates[type];
2466 knew->name = kstrdup(name, GFP_KERNEL);
2469 knew->private_value = val;
2470 spec->num_kctl_used++;
2474 #define AD1988_PIN_CD_NID 0x18
2475 #define AD1988_PIN_BEEP_NID 0x10
2477 static hda_nid_t ad1988_mixer_nids[8] = {
2478 /* A B C D E F G H */
2479 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2482 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2484 static hda_nid_t idx_to_dac[8] = {
2485 /* A B C D E F G H */
2486 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2488 static hda_nid_t idx_to_dac_rev2[8] = {
2489 /* A B C D E F G H */
2490 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2493 return idx_to_dac_rev2[idx];
2495 return idx_to_dac[idx];
2498 static hda_nid_t ad1988_boost_nids[8] = {
2499 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2502 static int ad1988_pin_idx(hda_nid_t nid)
2504 static hda_nid_t ad1988_io_pins[8] = {
2505 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2508 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2509 if (ad1988_io_pins[i] == nid)
2511 return 0; /* should be -1 */
2514 static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2516 static int loopback_idx[8] = {
2517 2, 0, 1, 3, 4, 5, 1, 4
2520 case AD1988_PIN_CD_NID:
2523 return loopback_idx[ad1988_pin_idx(nid)];
2527 static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2529 static int adc_idx[8] = {
2530 0, 1, 2, 8, 4, 3, 6, 7
2533 case AD1988_PIN_CD_NID:
2536 return adc_idx[ad1988_pin_idx(nid)];
2540 /* fill in the dac_nids table from the parsed pin configuration */
2541 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2542 const struct auto_pin_cfg *cfg)
2544 struct ad198x_spec *spec = codec->spec;
2547 spec->multiout.dac_nids = spec->private_dac_nids;
2549 /* check the pins hardwired to audio widget */
2550 for (i = 0; i < cfg->line_outs; i++) {
2551 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2552 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2554 spec->multiout.num_dacs = cfg->line_outs;
2558 /* add playback controls from the parsed DAC table */
2559 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2560 const struct auto_pin_cfg *cfg)
2563 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2567 for (i = 0; i < cfg->line_outs; i++) {
2568 hda_nid_t dac = spec->multiout.dac_nids[i];
2571 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2574 err = add_control(spec, AD_CTL_WIDGET_VOL,
2575 "Center Playback Volume",
2576 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2579 err = add_control(spec, AD_CTL_WIDGET_VOL,
2580 "LFE Playback Volume",
2581 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2584 err = add_control(spec, AD_CTL_BIND_MUTE,
2585 "Center Playback Switch",
2586 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2589 err = add_control(spec, AD_CTL_BIND_MUTE,
2590 "LFE Playback Switch",
2591 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2595 sprintf(name, "%s Playback Volume", chname[i]);
2596 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2597 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2600 sprintf(name, "%s Playback Switch", chname[i]);
2601 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2602 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2610 /* add playback controls for speaker and HP outputs */
2611 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2614 struct ad198x_spec *spec = codec->spec;
2622 idx = ad1988_pin_idx(pin);
2623 nid = ad1988_idx_to_dac(codec, idx);
2624 /* specify the DAC as the extra output */
2625 if (! spec->multiout.hp_nid)
2626 spec->multiout.hp_nid = nid;
2628 spec->multiout.extra_out_nid[0] = nid;
2629 /* control HP volume/switch on the output mixer amp */
2630 sprintf(name, "%s Playback Volume", pfx);
2631 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2632 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2634 nid = ad1988_mixer_nids[idx];
2635 sprintf(name, "%s Playback Switch", pfx);
2636 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2637 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2642 /* create input playback/capture controls for the given pin */
2643 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2644 const char *ctlname, int boost)
2649 sprintf(name, "%s Playback Volume", ctlname);
2650 idx = ad1988_pin_to_loopback_idx(pin);
2651 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2652 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2654 sprintf(name, "%s Playback Switch", ctlname);
2655 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2656 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2660 idx = ad1988_pin_idx(pin);
2661 bnid = ad1988_boost_nids[idx];
2663 sprintf(name, "%s Boost", ctlname);
2664 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2665 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2672 /* create playback/capture controls for input pins */
2673 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
2674 const struct auto_pin_cfg *cfg)
2676 struct hda_input_mux *imux = &spec->private_imux;
2679 for (i = 0; i < AUTO_PIN_LAST; i++) {
2680 err = new_analog_input(spec, cfg->input_pins[i],
2681 auto_pin_cfg_labels[i],
2682 i <= AUTO_PIN_FRONT_MIC);
2685 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2686 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2689 imux->items[imux->num_items].label = "Mix";
2690 imux->items[imux->num_items].index = 9;
2693 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2694 "Analog Mix Playback Volume",
2695 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2697 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2698 "Analog Mix Playback Switch",
2699 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2705 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2706 hda_nid_t nid, int pin_type,
2710 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2711 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2713 case 0x11: /* port-A - DAC 04 */
2714 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2716 case 0x14: /* port-B - DAC 06 */
2717 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2719 case 0x15: /* port-C - DAC 05 */
2720 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2722 case 0x17: /* port-E - DAC 0a */
2723 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2725 case 0x13: /* mono - DAC 04 */
2726 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2731 static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2733 struct ad198x_spec *spec = codec->spec;
2736 for (i = 0; i < spec->autocfg.line_outs; i++) {
2737 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2738 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2742 static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2744 struct ad198x_spec *spec = codec->spec;
2747 pin = spec->autocfg.speaker_pins[0];
2748 if (pin) /* connect to front */
2749 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2750 pin = spec->autocfg.hp_pins[0];
2751 if (pin) /* connect to front */
2752 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2755 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2757 struct ad198x_spec *spec = codec->spec;
2760 for (i = 0; i < AUTO_PIN_LAST; i++) {
2761 hda_nid_t nid = spec->autocfg.input_pins[i];
2765 case 0x15: /* port-C */
2766 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2768 case 0x17: /* port-E */
2769 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
2772 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2773 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2774 if (nid != AD1988_PIN_CD_NID)
2775 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2777 idx = ad1988_pin_idx(nid);
2778 if (ad1988_boost_nids[idx])
2779 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
2780 AC_VERB_SET_AMP_GAIN_MUTE,
2785 /* parse the BIOS configuration and set up the alc_spec */
2786 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2787 static int ad1988_parse_auto_config(struct hda_codec *codec)
2789 struct ad198x_spec *spec = codec->spec;
2792 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
2794 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
2796 if (! spec->autocfg.line_outs)
2797 return 0; /* can't find valid BIOS pin config */
2798 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2799 (err = ad1988_auto_create_extra_out(codec,
2800 spec->autocfg.speaker_pins[0],
2802 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2803 "Headphone")) < 0 ||
2804 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2807 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2809 if (spec->autocfg.dig_out_pin)
2810 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2811 if (spec->autocfg.dig_in_pin)
2812 spec->dig_in_nid = AD1988_SPDIF_IN;
2814 if (spec->kctl_alloc)
2815 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2817 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
2819 spec->input_mux = &spec->private_imux;
2824 /* init callback for auto-configuration model -- overriding the default init */
2825 static int ad1988_auto_init(struct hda_codec *codec)
2828 ad1988_auto_init_multi_out(codec);
2829 ad1988_auto_init_extra_out(codec);
2830 ad1988_auto_init_analog_input(codec);
2838 static const char *ad1988_models[AD1988_MODEL_LAST] = {
2839 [AD1988_6STACK] = "6stack",
2840 [AD1988_6STACK_DIG] = "6stack-dig",
2841 [AD1988_3STACK] = "3stack",
2842 [AD1988_3STACK_DIG] = "3stack-dig",
2843 [AD1988_LAPTOP] = "laptop",
2844 [AD1988_LAPTOP_DIG] = "laptop-dig",
2845 [AD1988_AUTO] = "auto",
2848 static struct snd_pci_quirk ad1988_cfg_tbl[] = {
2849 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
2850 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
2854 static int patch_ad1988(struct hda_codec *codec)
2856 struct ad198x_spec *spec;
2859 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2866 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2868 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2869 ad1988_models, ad1988_cfg_tbl);
2870 if (board_config < 0) {
2871 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2872 board_config = AD1988_AUTO;
2875 if (board_config == AD1988_AUTO) {
2876 /* automatic parse from the BIOS config */
2877 int err = ad1988_parse_auto_config(codec);
2882 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
2883 board_config = AD1988_6STACK;
2887 switch (board_config) {
2889 case AD1988_6STACK_DIG:
2890 spec->multiout.max_channels = 8;
2891 spec->multiout.num_dacs = 4;
2893 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
2895 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
2896 spec->input_mux = &ad1988_6stack_capture_source;
2897 spec->num_mixers = 2;
2899 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
2901 spec->mixers[0] = ad1988_6stack_mixers1;
2902 spec->mixers[1] = ad1988_6stack_mixers2;
2903 spec->num_init_verbs = 1;
2904 spec->init_verbs[0] = ad1988_6stack_init_verbs;
2905 if (board_config == AD1988_6STACK_DIG) {
2906 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2907 spec->dig_in_nid = AD1988_SPDIF_IN;
2911 case AD1988_3STACK_DIG:
2912 spec->multiout.max_channels = 6;
2913 spec->multiout.num_dacs = 3;
2915 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
2917 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2918 spec->input_mux = &ad1988_6stack_capture_source;
2919 spec->channel_mode = ad1988_3stack_modes;
2920 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
2921 spec->num_mixers = 2;
2923 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
2925 spec->mixers[0] = ad1988_3stack_mixers1;
2926 spec->mixers[1] = ad1988_3stack_mixers2;
2927 spec->num_init_verbs = 1;
2928 spec->init_verbs[0] = ad1988_3stack_init_verbs;
2929 if (board_config == AD1988_3STACK_DIG)
2930 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2933 case AD1988_LAPTOP_DIG:
2934 spec->multiout.max_channels = 2;
2935 spec->multiout.num_dacs = 1;
2936 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
2937 spec->input_mux = &ad1988_laptop_capture_source;
2938 spec->num_mixers = 1;
2939 spec->mixers[0] = ad1988_laptop_mixers;
2940 spec->num_init_verbs = 1;
2941 spec->init_verbs[0] = ad1988_laptop_init_verbs;
2942 if (board_config == AD1988_LAPTOP_DIG)
2943 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
2947 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
2948 spec->adc_nids = ad1988_adc_nids;
2949 spec->capsrc_nids = ad1988_capsrc_nids;
2950 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
2951 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
2952 if (spec->multiout.dig_out_nid) {
2953 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
2954 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
2956 if (spec->dig_in_nid)
2957 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
2959 codec->patch_ops = ad198x_patch_ops;
2960 switch (board_config) {
2962 codec->patch_ops.init = ad1988_auto_init;
2965 case AD1988_LAPTOP_DIG:
2966 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
2969 #ifdef CONFIG_SND_HDA_POWER_SAVE
2970 spec->loopback.amplist = ad1988_loopbacks;
2972 spec->vmaster_nid = 0x04;
2981 * port-B - front line/mic-in
2982 * port-E - aux in/out
2983 * port-F - aux in/out
2984 * port-C - rear line/mic-in
2985 * port-D - rear line/hp-out
2986 * port-A - front line/hp-out
2988 * AD1984 = AD1884 + two digital mic-ins
2991 * For simplicity, we share the single DAC for both HP and line-outs
2992 * right now. The inidividual playbacks could be easily implemented,
2993 * but no build-up framework is given, so far.
2996 static hda_nid_t ad1884_dac_nids[1] = {
3000 static hda_nid_t ad1884_adc_nids[2] = {
3004 static hda_nid_t ad1884_capsrc_nids[2] = {
3008 #define AD1884_SPDIF_OUT 0x02
3010 static struct hda_input_mux ad1884_capture_source = {
3013 { "Front Mic", 0x0 },
3020 static struct snd_kcontrol_new ad1884_base_mixers[] = {
3021 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3022 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3023 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3024 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3025 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3026 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3027 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3028 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3029 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3030 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3031 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3032 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3034 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3035 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3036 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
3037 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
3039 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3040 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3041 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3042 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3043 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3044 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3046 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3047 /* The multiple "Capture Source" controls confuse alsamixer
3048 * So call somewhat different..
3050 /* .name = "Capture Source", */
3051 .name = "Input Source",
3053 .info = ad198x_mux_enum_info,
3054 .get = ad198x_mux_enum_get,
3055 .put = ad198x_mux_enum_put,
3057 /* SPDIF controls */
3058 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3060 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3061 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3062 /* identical with ad1983 */
3063 .info = ad1983_spdif_route_info,
3064 .get = ad1983_spdif_route_get,
3065 .put = ad1983_spdif_route_put,
3070 static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3071 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3072 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3073 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3075 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3081 * initialization verbs
3083 static struct hda_verb ad1884_init_verbs[] = {
3084 /* DACs; mute as default */
3085 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3086 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3087 /* Port-A (HP) mixer */
3088 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3089 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3091 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3092 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3093 /* HP selector - select DAC2 */
3094 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3095 /* Port-D (Line-out) mixer */
3096 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3097 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3099 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3100 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3101 /* Mono-out mixer */
3102 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3103 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3105 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3106 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3108 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3109 /* Port-B (front mic) pin */
3110 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3111 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3112 /* Port-C (rear mic) pin */
3113 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3114 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3115 /* Analog mixer; mute as default */
3116 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3117 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3118 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3119 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3120 /* Analog Mix output amp */
3121 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3122 /* SPDIF output selector */
3123 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3124 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3128 #ifdef CONFIG_SND_HDA_POWER_SAVE
3129 static struct hda_amp_list ad1884_loopbacks[] = {
3130 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3131 { 0x20, HDA_INPUT, 1 }, /* Mic */
3132 { 0x20, HDA_INPUT, 2 }, /* CD */
3133 { 0x20, HDA_INPUT, 4 }, /* Docking */
3138 static const char *ad1884_slave_vols[] = {
3139 "PCM Playback Volume",
3140 "Mic Playback Volume",
3141 "Mono Playback Volume",
3142 "Front Mic Playback Volume",
3143 "Mic Playback Volume",
3144 "CD Playback Volume",
3145 "Internal Mic Playback Volume",
3146 "Docking Mic Playback Volume"
3147 "Beep Playback Volume",
3148 "IEC958 Playback Volume",
3152 static int patch_ad1884(struct hda_codec *codec)
3154 struct ad198x_spec *spec;
3156 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3160 mutex_init(&spec->amp_mutex);
3163 spec->multiout.max_channels = 2;
3164 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3165 spec->multiout.dac_nids = ad1884_dac_nids;
3166 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3167 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3168 spec->adc_nids = ad1884_adc_nids;
3169 spec->capsrc_nids = ad1884_capsrc_nids;
3170 spec->input_mux = &ad1884_capture_source;
3171 spec->num_mixers = 1;
3172 spec->mixers[0] = ad1884_base_mixers;
3173 spec->num_init_verbs = 1;
3174 spec->init_verbs[0] = ad1884_init_verbs;
3175 spec->spdif_route = 0;
3176 #ifdef CONFIG_SND_HDA_POWER_SAVE
3177 spec->loopback.amplist = ad1884_loopbacks;
3179 spec->vmaster_nid = 0x04;
3180 /* we need to cover all playback volumes */
3181 spec->slave_vols = ad1884_slave_vols;
3183 codec->patch_ops = ad198x_patch_ops;
3189 * Lenovo Thinkpad T61/X61
3191 static struct hda_input_mux ad1984_thinkpad_capture_source = {
3195 { "Internal Mic", 0x1 },
3197 { "Docking-Station", 0x4 },
3203 * Dell Precision T3400
3205 static struct hda_input_mux ad1984_dell_desktop_capture_source = {
3208 { "Front Mic", 0x0 },
3215 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3216 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3217 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3218 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3219 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3220 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3221 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3222 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3223 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3224 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3225 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3226 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3227 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3228 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3229 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3230 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3231 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3232 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3233 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3234 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3236 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3237 /* The multiple "Capture Source" controls confuse alsamixer
3238 * So call somewhat different..
3240 /* .name = "Capture Source", */
3241 .name = "Input Source",
3243 .info = ad198x_mux_enum_info,
3244 .get = ad198x_mux_enum_get,
3245 .put = ad198x_mux_enum_put,
3247 /* SPDIF controls */
3248 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3250 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3251 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3252 /* identical with ad1983 */
3253 .info = ad1983_spdif_route_info,
3254 .get = ad1983_spdif_route_get,
3255 .put = ad1983_spdif_route_put,
3260 /* additional verbs */
3261 static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3262 /* Port-E (docking station mic) pin */
3263 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3264 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3265 /* docking mic boost */
3266 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3267 /* Analog mixer - docking mic; mute as default */
3268 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3269 /* enable EAPD bit */
3270 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3275 * Dell Precision T3400
3277 static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3278 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3279 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3280 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3281 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3282 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3283 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3284 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3285 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3286 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3288 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
3289 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
3291 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
3292 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3293 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3294 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3295 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3296 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3298 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3299 /* The multiple "Capture Source" controls confuse alsamixer
3300 * So call somewhat different..
3302 /* .name = "Capture Source", */
3303 .name = "Input Source",
3305 .info = ad198x_mux_enum_info,
3306 .get = ad198x_mux_enum_get,
3307 .put = ad198x_mux_enum_put,
3312 /* Digial MIC ADC NID 0x05 + 0x06 */
3313 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3314 struct hda_codec *codec,
3315 unsigned int stream_tag,
3316 unsigned int format,
3317 struct snd_pcm_substream *substream)
3319 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3320 stream_tag, 0, format);
3324 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3325 struct hda_codec *codec,
3326 struct snd_pcm_substream *substream)
3328 snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3333 static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3339 .prepare = ad1984_pcm_dmic_prepare,
3340 .cleanup = ad1984_pcm_dmic_cleanup
3344 static int ad1984_build_pcms(struct hda_codec *codec)
3346 struct ad198x_spec *spec = codec->spec;
3347 struct hda_pcm *info;
3350 err = ad198x_build_pcms(codec);
3354 info = spec->pcm_rec + codec->num_pcms;
3356 info->name = "AD1984 Digital Mic";
3357 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3365 AD1984_DELL_DESKTOP,
3369 static const char *ad1984_models[AD1984_MODELS] = {
3370 [AD1984_BASIC] = "basic",
3371 [AD1984_THINKPAD] = "thinkpad",
3372 [AD1984_DELL_DESKTOP] = "dell_desktop",
3375 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
3376 /* Lenovo Thinkpad T61/X61 */
3377 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
3378 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3382 static int patch_ad1984(struct hda_codec *codec)
3384 struct ad198x_spec *spec;
3385 int board_config, err;
3387 err = patch_ad1884(codec);
3391 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3392 ad1984_models, ad1984_cfg_tbl);
3393 switch (board_config) {
3395 /* additional digital mics */
3396 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3397 codec->patch_ops.build_pcms = ad1984_build_pcms;
3399 case AD1984_THINKPAD:
3400 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3401 spec->input_mux = &ad1984_thinkpad_capture_source;
3402 spec->mixers[0] = ad1984_thinkpad_mixers;
3403 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3405 case AD1984_DELL_DESKTOP:
3406 spec->multiout.dig_out_nid = 0;
3407 spec->input_mux = &ad1984_dell_desktop_capture_source;
3408 spec->mixers[0] = ad1984_dell_desktop_mixers;
3416 * AD1883 / AD1884A / AD1984A / AD1984B
3418 * port-B (0x14) - front mic-in
3419 * port-E (0x1c) - rear mic-in
3420 * port-F (0x16) - CD / ext out
3421 * port-C (0x15) - rear line-in
3422 * port-D (0x12) - rear line-out
3423 * port-A (0x11) - front hp-out
3425 * AD1984A = AD1884A + digital-mic
3426 * AD1883 = equivalent with AD1984A
3427 * AD1984B = AD1984A + extra SPDIF-out
3430 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3433 static hda_nid_t ad1884a_dac_nids[1] = {
3437 #define ad1884a_adc_nids ad1884_adc_nids
3438 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3440 #define AD1884A_SPDIF_OUT 0x02
3442 static struct hda_input_mux ad1884a_capture_source = {
3445 { "Front Mic", 0x0 },
3453 static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3454 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3455 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3456 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3457 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3458 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3459 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3460 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3461 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3462 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3463 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3464 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3465 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3466 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3467 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3468 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3469 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3470 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3471 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3472 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3473 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3474 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3475 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3476 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3477 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3478 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3481 /* The multiple "Capture Source" controls confuse alsamixer
3482 * So call somewhat different..
3484 /* .name = "Capture Source", */
3485 .name = "Input Source",
3487 .info = ad198x_mux_enum_info,
3488 .get = ad198x_mux_enum_get,
3489 .put = ad198x_mux_enum_put,
3491 /* SPDIF controls */
3492 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3494 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3495 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3496 /* identical with ad1983 */
3497 .info = ad1983_spdif_route_info,
3498 .get = ad1983_spdif_route_get,
3499 .put = ad1983_spdif_route_put,
3505 * initialization verbs
3507 static struct hda_verb ad1884a_init_verbs[] = {
3508 /* DACs; unmute as default */
3509 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3510 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3511 /* Port-A (HP) mixer - route only from analog mixer */
3512 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3513 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3515 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3516 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3517 /* Port-D (Line-out) mixer - route only from analog mixer */
3518 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3519 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3521 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3522 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3523 /* Mono-out mixer - route only from analog mixer */
3524 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3525 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3527 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3528 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3529 /* Port-B (front mic) pin */
3530 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3531 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3532 /* Port-C (rear line-in) pin */
3533 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3534 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3535 /* Port-E (rear mic) pin */
3536 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3537 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3538 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3539 /* Port-F (CD) pin */
3540 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3541 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3542 /* Analog mixer; mute as default */
3543 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3544 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3545 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3546 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3547 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3548 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3549 /* Analog Mix output amp */
3550 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3551 /* capture sources */
3552 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3553 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3554 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3555 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3556 /* SPDIF output amp */
3557 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3561 #ifdef CONFIG_SND_HDA_POWER_SAVE
3562 static struct hda_amp_list ad1884a_loopbacks[] = {
3563 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3564 { 0x20, HDA_INPUT, 1 }, /* Mic */
3565 { 0x20, HDA_INPUT, 2 }, /* CD */
3566 { 0x20, HDA_INPUT, 4 }, /* Docking */
3574 * Port A: Headphone jack
3576 * Port C: Internal MIC
3577 * Port D: Dock Line Out (if enabled)
3578 * Port E: Dock Line In (if enabled)
3579 * Port F: Internal speakers
3582 static struct hda_input_mux ad1884a_laptop_capture_source = {
3585 { "Mic", 0x0 }, /* port-B */
3586 { "Internal Mic", 0x1 }, /* port-C */
3587 { "Dock Mic", 0x4 }, /* port-E */
3592 static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3593 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3594 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3595 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3596 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3597 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3598 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3599 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3600 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3601 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3602 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3603 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3604 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3605 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3606 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3607 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3608 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3609 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3610 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3611 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3612 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3614 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3615 /* The multiple "Capture Source" controls confuse alsamixer
3616 * So call somewhat different..
3618 /* .name = "Capture Source", */
3619 .name = "Input Source",
3621 .info = ad198x_mux_enum_info,
3622 .get = ad198x_mux_enum_get,
3623 .put = ad198x_mux_enum_put,
3628 static struct hda_input_mux ad1884a_mobile_capture_source = {
3631 { "Mic", 0x1 }, /* port-C */
3636 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3637 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3638 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3639 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3640 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3641 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3642 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3643 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3644 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3645 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3646 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3647 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3649 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3650 .name = "Capture Source",
3651 .info = ad198x_mux_enum_info,
3652 .get = ad198x_mux_enum_get,
3653 .put = ad198x_mux_enum_put,
3658 /* mute internal speaker if HP is plugged */
3659 static void ad1884a_hp_automute(struct hda_codec *codec)
3661 unsigned int present;
3663 present = snd_hda_codec_read(codec, 0x11, 0,
3664 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
3665 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3666 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3667 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3668 present ? 0x00 : 0x02);
3671 #define AD1884A_HP_EVENT 0x37
3673 /* unsolicited event for HP jack sensing */
3674 static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3676 if ((res >> 26) != AD1884A_HP_EVENT)
3678 ad1884a_hp_automute(codec);
3681 /* initialize jack-sensing, too */
3682 static int ad1884a_hp_init(struct hda_codec *codec)
3685 ad1884a_hp_automute(codec);
3689 /* additional verbs for laptop model */
3690 static struct hda_verb ad1884a_laptop_verbs[] = {
3691 /* Port-A (HP) pin - always unmuted */
3692 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3693 /* Port-F (int speaker) mixer - route only from analog mixer */
3694 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3695 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3697 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3698 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3700 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3701 /* unsolicited event for pin-sense */
3702 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
3716 static const char *ad1884a_models[AD1884A_MODELS] = {
3717 [AD1884A_DESKTOP] = "desktop",
3718 [AD1884A_LAPTOP] = "laptop",
3719 [AD1884A_MOBILE] = "mobile",
3722 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3723 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
3727 static int patch_ad1884a(struct hda_codec *codec)
3729 struct ad198x_spec *spec;
3732 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3736 mutex_init(&spec->amp_mutex);
3739 spec->multiout.max_channels = 2;
3740 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
3741 spec->multiout.dac_nids = ad1884a_dac_nids;
3742 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
3743 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
3744 spec->adc_nids = ad1884a_adc_nids;
3745 spec->capsrc_nids = ad1884a_capsrc_nids;
3746 spec->input_mux = &ad1884a_capture_source;
3747 spec->num_mixers = 1;
3748 spec->mixers[0] = ad1884a_base_mixers;
3749 spec->num_init_verbs = 1;
3750 spec->init_verbs[0] = ad1884a_init_verbs;
3751 spec->spdif_route = 0;
3752 #ifdef CONFIG_SND_HDA_POWER_SAVE
3753 spec->loopback.amplist = ad1884a_loopbacks;
3755 codec->patch_ops = ad198x_patch_ops;
3757 /* override some parameters */
3758 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
3761 switch (board_config) {
3762 case AD1884A_LAPTOP:
3763 spec->mixers[0] = ad1884a_laptop_mixers;
3764 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3765 spec->multiout.dig_out_nid = 0;
3766 spec->input_mux = &ad1884a_laptop_capture_source;
3767 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3768 codec->patch_ops.init = ad1884a_hp_init;
3770 case AD1884A_MOBILE:
3771 spec->mixers[0] = ad1884a_mobile_mixers;
3772 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
3773 spec->multiout.dig_out_nid = 0;
3774 spec->input_mux = &ad1884a_mobile_capture_source;
3775 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
3776 codec->patch_ops.init = ad1884a_hp_init;
3787 * port-A - front hp-out
3788 * port-B - front mic-in
3789 * port-C - rear line-in, shared surr-out (3stack)
3790 * port-D - rear line-out
3791 * port-E - rear mic-in, shared clfe-out (3stack)
3792 * port-F - rear surr-out (6stack)
3793 * port-G - rear clfe-out (6stack)
3796 static hda_nid_t ad1882_dac_nids[3] = {
3800 static hda_nid_t ad1882_adc_nids[2] = {
3804 static hda_nid_t ad1882_capsrc_nids[2] = {
3808 #define AD1882_SPDIF_OUT 0x02
3810 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
3811 static struct hda_input_mux ad1882_capture_source = {
3814 { "Front Mic", 0x1 },
3822 static struct snd_kcontrol_new ad1882_base_mixers[] = {
3823 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3824 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
3825 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
3826 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
3827 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3828 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3829 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3830 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3831 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3832 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3833 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3834 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3835 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
3836 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
3837 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
3838 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
3839 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
3840 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
3841 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
3842 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
3843 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
3844 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3845 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3846 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3847 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3850 /* The multiple "Capture Source" controls confuse alsamixer
3851 * So call somewhat different..
3853 /* .name = "Capture Source", */
3854 .name = "Input Source",
3856 .info = ad198x_mux_enum_info,
3857 .get = ad198x_mux_enum_get,
3858 .put = ad198x_mux_enum_put,
3860 /* SPDIF controls */
3861 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3863 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3864 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3865 /* identical with ad1983 */
3866 .info = ad1983_spdif_route_info,
3867 .get = ad1983_spdif_route_get,
3868 .put = ad1983_spdif_route_put,
3873 static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
3874 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3875 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
3876 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
3878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3879 .name = "Channel Mode",
3880 .info = ad198x_ch_mode_info,
3881 .get = ad198x_ch_mode_get,
3882 .put = ad198x_ch_mode_put,
3887 static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
3888 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
3889 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
3890 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
3894 static struct hda_verb ad1882_ch2_init[] = {
3895 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3896 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3897 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3898 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3899 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3900 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3904 static struct hda_verb ad1882_ch4_init[] = {
3905 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3906 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3907 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3908 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3909 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3910 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3914 static struct hda_verb ad1882_ch6_init[] = {
3915 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3916 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3917 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3918 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3919 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3920 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3924 static struct hda_channel_mode ad1882_modes[3] = {
3925 { 2, ad1882_ch2_init },
3926 { 4, ad1882_ch4_init },
3927 { 6, ad1882_ch6_init },
3931 * initialization verbs
3933 static struct hda_verb ad1882_init_verbs[] = {
3934 /* DACs; mute as default */
3935 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3936 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3937 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3938 /* Port-A (HP) mixer */
3939 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3940 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3942 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3943 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3944 /* HP selector - select DAC2 */
3945 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
3946 /* Port-D (Line-out) mixer */
3947 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3948 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3950 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3951 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3952 /* Mono-out mixer */
3953 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3954 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3956 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3957 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3958 /* Port-B (front mic) pin */
3959 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3960 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3961 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3962 /* Port-C (line-in) pin */
3963 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3964 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3965 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3966 /* Port-C mixer - mute as input */
3967 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3968 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3969 /* Port-E (mic-in) pin */
3970 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3971 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3972 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
3973 /* Port-E mixer - mute as input */
3974 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3975 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3976 /* Port-F (surround) */
3977 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3978 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3980 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3981 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3982 /* Analog mixer; mute as default */
3983 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
3984 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3985 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3986 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3987 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3988 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3989 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3990 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3991 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3992 /* Analog Mix output amp */
3993 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3994 /* SPDIF output selector */
3995 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3996 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3997 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4001 #ifdef CONFIG_SND_HDA_POWER_SAVE
4002 static struct hda_amp_list ad1882_loopbacks[] = {
4003 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4004 { 0x20, HDA_INPUT, 1 }, /* Mic */
4005 { 0x20, HDA_INPUT, 4 }, /* Line */
4006 { 0x20, HDA_INPUT, 6 }, /* CD */
4018 static const char *ad1882_models[AD1986A_MODELS] = {
4019 [AD1882_3STACK] = "3stack",
4020 [AD1882_6STACK] = "6stack",
4024 static int patch_ad1882(struct hda_codec *codec)
4026 struct ad198x_spec *spec;
4029 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4033 mutex_init(&spec->amp_mutex);
4036 spec->multiout.max_channels = 6;
4037 spec->multiout.num_dacs = 3;
4038 spec->multiout.dac_nids = ad1882_dac_nids;
4039 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4040 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4041 spec->adc_nids = ad1882_adc_nids;
4042 spec->capsrc_nids = ad1882_capsrc_nids;
4043 spec->input_mux = &ad1882_capture_source;
4044 spec->num_mixers = 1;
4045 spec->mixers[0] = ad1882_base_mixers;
4046 spec->num_init_verbs = 1;
4047 spec->init_verbs[0] = ad1882_init_verbs;
4048 spec->spdif_route = 0;
4049 #ifdef CONFIG_SND_HDA_POWER_SAVE
4050 spec->loopback.amplist = ad1882_loopbacks;
4052 spec->vmaster_nid = 0x04;
4054 codec->patch_ops = ad198x_patch_ops;
4056 /* override some parameters */
4057 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4058 ad1882_models, NULL);
4059 switch (board_config) {
4062 spec->num_mixers = 2;
4063 spec->mixers[1] = ad1882_3stack_mixers;
4064 spec->channel_mode = ad1882_modes;
4065 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4066 spec->need_dac_fix = 1;
4067 spec->multiout.max_channels = 2;
4068 spec->multiout.num_dacs = 1;
4071 spec->num_mixers = 2;
4072 spec->mixers[1] = ad1882_6stack_mixers;
4082 struct hda_codec_preset snd_hda_preset_analog[] = {
4083 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4084 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4085 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4086 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4087 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4088 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4089 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4090 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4091 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4092 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4093 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4094 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },