2 * HD audio interface patch for AD1981HD, AD1983, AD1986A
4 * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This driver is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
31 struct snd_kcontrol_new *mixers[5];
34 const struct hda_verb *init_verbs[3]; /* initialization verbs
35 * don't forget NULL termination!
37 unsigned int num_init_verbs;
40 struct hda_multi_out multiout; /* playback set-up
41 * max_channels, dacs must be set
42 * dig_out_nid and hp_nid are optional
44 unsigned int cur_eapd;
47 unsigned int num_adc_nids;
49 hda_nid_t dig_in_nid; /* digital-in NID; optional */
52 const struct hda_input_mux *input_mux;
53 unsigned int cur_mux[3];
56 const struct hda_channel_mode *channel_mode;
60 struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */
62 struct semaphore amp_mutex; /* PCM volume/mute control mutex */
63 unsigned int spdif_route;
67 * input MUX handling (common part)
69 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
71 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
72 struct ad198x_spec *spec = codec->spec;
74 return snd_hda_input_mux_info(spec->input_mux, uinfo);
77 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
79 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
80 struct ad198x_spec *spec = codec->spec;
81 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
83 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
87 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
89 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
90 struct ad198x_spec *spec = codec->spec;
91 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
93 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
94 spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
98 * initialization (common callbacks)
100 static int ad198x_init(struct hda_codec *codec)
102 struct ad198x_spec *spec = codec->spec;
105 for (i = 0; i < spec->num_init_verbs; i++)
106 snd_hda_sequence_write(codec, spec->init_verbs[i]);
110 static int ad198x_build_controls(struct hda_codec *codec)
112 struct ad198x_spec *spec = codec->spec;
116 for (i = 0; i < spec->num_mixers; i++) {
117 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
121 if (spec->multiout.dig_out_nid) {
122 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
126 if (spec->dig_in_nid) {
127 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
135 * Analog playback callbacks
137 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
138 struct hda_codec *codec,
139 struct snd_pcm_substream *substream)
141 struct ad198x_spec *spec = codec->spec;
142 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
145 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
146 struct hda_codec *codec,
147 unsigned int stream_tag,
149 struct snd_pcm_substream *substream)
151 struct ad198x_spec *spec = codec->spec;
152 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
156 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
157 struct hda_codec *codec,
158 struct snd_pcm_substream *substream)
160 struct ad198x_spec *spec = codec->spec;
161 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
167 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
168 struct hda_codec *codec,
169 struct snd_pcm_substream *substream)
171 struct ad198x_spec *spec = codec->spec;
172 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
175 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
176 struct hda_codec *codec,
177 struct snd_pcm_substream *substream)
179 struct ad198x_spec *spec = codec->spec;
180 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
186 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
187 struct hda_codec *codec,
188 unsigned int stream_tag,
190 struct snd_pcm_substream *substream)
192 struct ad198x_spec *spec = codec->spec;
193 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
194 stream_tag, 0, format);
198 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
199 struct hda_codec *codec,
200 struct snd_pcm_substream *substream)
202 struct ad198x_spec *spec = codec->spec;
203 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
211 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
214 .channels_max = 6, /* changed later */
215 .nid = 0, /* fill later */
217 .open = ad198x_playback_pcm_open,
218 .prepare = ad198x_playback_pcm_prepare,
219 .cleanup = ad198x_playback_pcm_cleanup
223 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
227 .nid = 0, /* fill later */
229 .prepare = ad198x_capture_pcm_prepare,
230 .cleanup = ad198x_capture_pcm_cleanup
234 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
238 .nid = 0, /* fill later */
240 .open = ad198x_dig_playback_pcm_open,
241 .close = ad198x_dig_playback_pcm_close
245 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
249 /* NID is set in alc_build_pcms */
252 static int ad198x_build_pcms(struct hda_codec *codec)
254 struct ad198x_spec *spec = codec->spec;
255 struct hda_pcm *info = spec->pcm_rec;
258 codec->pcm_info = info;
260 info->name = "AD198x Analog";
261 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
262 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
263 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
264 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
265 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
266 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
268 if (spec->multiout.dig_out_nid) {
271 info->name = "AD198x Digital";
272 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
273 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
274 if (spec->dig_in_nid) {
275 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
276 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
283 static void ad198x_free(struct hda_codec *codec)
289 static int ad198x_resume(struct hda_codec *codec)
291 struct ad198x_spec *spec = codec->spec;
295 for (i = 0; i < spec->num_mixers; i++)
296 snd_hda_resume_ctls(codec, spec->mixers[i]);
297 if (spec->multiout.dig_out_nid)
298 snd_hda_resume_spdif_out(codec);
299 if (spec->dig_in_nid)
300 snd_hda_resume_spdif_in(codec);
305 static struct hda_codec_ops ad198x_patch_ops = {
306 .build_controls = ad198x_build_controls,
307 .build_pcms = ad198x_build_pcms,
311 .resume = ad198x_resume,
320 #define AD1986A_SPDIF_OUT 0x02
321 #define AD1986A_FRONT_DAC 0x03
322 #define AD1986A_SURR_DAC 0x04
323 #define AD1986A_CLFE_DAC 0x05
324 #define AD1986A_ADC 0x06
326 static hda_nid_t ad1986a_dac_nids[3] = {
327 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
329 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
331 static struct hda_input_mux ad1986a_capture_source = {
347 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
350 #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
352 static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
354 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
355 struct ad198x_spec *ad = codec->spec;
357 down(&ad->amp_mutex);
358 snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
363 static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
365 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
366 struct ad198x_spec *ad = codec->spec;
369 down(&ad->amp_mutex);
370 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
371 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
372 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
374 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
379 #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
381 static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
383 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
384 struct ad198x_spec *ad = codec->spec;
386 down(&ad->amp_mutex);
387 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
392 static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
394 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
395 struct ad198x_spec *ad = codec->spec;
398 down(&ad->amp_mutex);
399 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
400 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
401 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
403 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
411 static struct snd_kcontrol_new ad1986a_mixers[] = {
413 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
414 .name = "PCM Playback Volume",
415 .info = ad1986a_pcm_amp_vol_info,
416 .get = ad1986a_pcm_amp_vol_get,
417 .put = ad1986a_pcm_amp_vol_put,
418 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
421 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
422 .name = "PCM Playback Switch",
423 .info = ad1986a_pcm_amp_sw_info,
424 .get = ad1986a_pcm_amp_sw_get,
425 .put = ad1986a_pcm_amp_sw_put,
426 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
428 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
429 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
430 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
431 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
432 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
433 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
434 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
435 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
436 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
437 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
438 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
439 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
440 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
441 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
442 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
443 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
444 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
445 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
446 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
447 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
448 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
449 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
450 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
451 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
454 .name = "Capture Source",
455 .info = ad198x_mux_enum_info,
456 .get = ad198x_mux_enum_get,
457 .put = ad198x_mux_enum_put,
459 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
464 * initialization verbs
466 static struct hda_verb ad1986a_init_verbs[] = {
467 /* Front, Surround, CLFE DAC; mute as default */
468 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
469 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
470 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
472 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
473 /* HP, Line-Out, Surround, CLFE selectors */
474 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
475 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
476 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
477 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
479 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
480 /* Mic selector: Mic 1/2 pin */
481 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
482 /* Line-in selector: Line-in */
483 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
485 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
486 /* Record selector: mic */
487 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
488 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
489 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
490 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
491 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
492 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
493 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
495 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
496 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
497 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
498 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
499 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
500 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
501 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
503 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
504 /* Front, Surround, CLFE Pins */
505 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
506 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
507 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
509 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
511 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
512 /* Line, Aux, CD, Beep-In Pin */
513 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
514 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
515 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
516 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
517 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
522 static int patch_ad1986a(struct hda_codec *codec)
524 struct ad198x_spec *spec;
526 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
530 init_MUTEX(&spec->amp_mutex);
533 spec->multiout.max_channels = 6;
534 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
535 spec->multiout.dac_nids = ad1986a_dac_nids;
536 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
537 spec->num_adc_nids = 1;
538 spec->adc_nids = ad1986a_adc_nids;
539 spec->input_mux = &ad1986a_capture_source;
540 spec->num_mixers = 1;
541 spec->mixers[0] = ad1986a_mixers;
542 spec->num_init_verbs = 1;
543 spec->init_verbs[0] = ad1986a_init_verbs;
545 codec->patch_ops = ad198x_patch_ops;
554 #define AD1983_SPDIF_OUT 0x02
555 #define AD1983_DAC 0x03
556 #define AD1983_ADC 0x04
558 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
559 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
561 static struct hda_input_mux ad1983_capture_source = {
572 * SPDIF playback route
574 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
576 static char *texts[] = { "PCM", "ADC" };
578 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
580 uinfo->value.enumerated.items = 2;
581 if (uinfo->value.enumerated.item > 1)
582 uinfo->value.enumerated.item = 1;
583 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
587 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
589 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
590 struct ad198x_spec *spec = codec->spec;
592 ucontrol->value.enumerated.item[0] = spec->spdif_route;
596 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
598 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
599 struct ad198x_spec *spec = codec->spec;
601 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
602 spec->spdif_route = ucontrol->value.enumerated.item[0];
603 snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
604 AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
610 static struct snd_kcontrol_new ad1983_mixers[] = {
611 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
612 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
613 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
614 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
615 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
616 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
617 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
618 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
619 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
620 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
621 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
622 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
623 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
624 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
625 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
626 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
627 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
629 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
630 .name = "Capture Source",
631 .info = ad198x_mux_enum_info,
632 .get = ad198x_mux_enum_get,
633 .put = ad198x_mux_enum_put,
636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
637 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
638 .info = ad1983_spdif_route_info,
639 .get = ad1983_spdif_route_get,
640 .put = ad1983_spdif_route_put,
645 static struct hda_verb ad1983_init_verbs[] = {
646 /* Front, HP, Mono; mute as default */
647 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
648 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
649 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
650 /* Beep, PCM, Mic, Line-In: mute */
651 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
652 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
653 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
654 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
655 /* Front, HP selectors; from Mix */
656 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
657 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
658 /* Mono selector; from Mix */
659 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
660 /* Mic selector; Mic */
661 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
662 /* Line-in selector: Line-in */
663 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
665 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
666 /* Record selector: mic */
667 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
668 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
669 /* SPDIF route: PCM */
670 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
672 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
674 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
676 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
678 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
680 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
685 static int patch_ad1983(struct hda_codec *codec)
687 struct ad198x_spec *spec;
689 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
693 init_MUTEX(&spec->amp_mutex);
696 spec->multiout.max_channels = 2;
697 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
698 spec->multiout.dac_nids = ad1983_dac_nids;
699 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
700 spec->num_adc_nids = 1;
701 spec->adc_nids = ad1983_adc_nids;
702 spec->input_mux = &ad1983_capture_source;
703 spec->num_mixers = 1;
704 spec->mixers[0] = ad1983_mixers;
705 spec->num_init_verbs = 1;
706 spec->init_verbs[0] = ad1983_init_verbs;
707 spec->spdif_route = 0;
709 codec->patch_ops = ad198x_patch_ops;
719 #define AD1981_SPDIF_OUT 0x02
720 #define AD1981_DAC 0x03
721 #define AD1981_ADC 0x04
723 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
724 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
726 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
727 static struct hda_input_mux ad1981_capture_source = {
730 { "Front Mic", 0x0 },
740 static struct snd_kcontrol_new ad1981_mixers[] = {
741 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
742 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
743 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
744 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
745 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
746 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
747 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
748 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
749 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
750 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
751 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
752 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
753 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
754 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
755 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
756 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
757 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
758 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
759 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
760 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
761 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
762 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
763 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
764 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
767 .name = "Capture Source",
768 .info = ad198x_mux_enum_info,
769 .get = ad198x_mux_enum_get,
770 .put = ad198x_mux_enum_put,
772 /* identical with AD1983 */
774 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
775 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
776 .info = ad1983_spdif_route_info,
777 .get = ad1983_spdif_route_get,
778 .put = ad1983_spdif_route_put,
783 static struct hda_verb ad1981_init_verbs[] = {
784 /* Front, HP, Mono; mute as default */
785 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
786 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
787 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
788 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
789 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
790 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
791 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
792 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
793 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
794 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
795 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
796 /* Front, HP selectors; from Mix */
797 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
798 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
799 /* Mono selector; from Mix */
800 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
801 /* Mic Mixer; select Front Mic */
802 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
803 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
805 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
806 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
807 /* Record selector: Front mic */
808 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
809 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
810 /* SPDIF route: PCM */
811 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
813 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
815 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
817 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
818 /* Front & Rear Mic Pins */
819 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
820 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
822 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
824 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
825 /* Line-Out as Input: disabled */
826 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
830 static int patch_ad1981(struct hda_codec *codec)
832 struct ad198x_spec *spec;
834 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
838 init_MUTEX(&spec->amp_mutex);
841 spec->multiout.max_channels = 2;
842 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
843 spec->multiout.dac_nids = ad1981_dac_nids;
844 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
845 spec->num_adc_nids = 1;
846 spec->adc_nids = ad1981_adc_nids;
847 spec->input_mux = &ad1981_capture_source;
848 spec->num_mixers = 1;
849 spec->mixers[0] = ad1981_mixers;
850 spec->num_init_verbs = 1;
851 spec->init_verbs[0] = ad1981_init_verbs;
852 spec->spdif_route = 0;
854 codec->patch_ops = ad198x_patch_ops;
863 * Output pins and routes
866 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
867 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
868 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
869 * port-D 0x12 (mute/hp) <- 0x29 <- 04
870 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
871 * port-F 0x16 (mute) <- 0x2a <- 06
872 * port-G 0x24 (mute) <- 0x27 <- 05
873 * port-H 0x25 (mute) <- 0x28 <- 0a
874 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
877 * Input pins and routes
879 * pin boost mix input # / adc input #
880 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
881 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
882 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
883 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
884 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
885 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
886 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
887 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
897 * Inputs of Analog Mix (0x20)
898 * 0:Port-B (front mic)
899 * 1:Port-C/G/H (line-in)
901 * 3:Port-D (line-in/2)
902 * 4:Port-E/G/H (mic-in)
909 * 1:Port-B (front mic-in)
916 * 8:Port-D (line-in/2)
919 * Proposed pin assignments by the datasheet
922 * Port-A front headphone
932 * Port-A front headphone
934 * C rear line-in/surround
942 * D internal speaker (with EAPD)
963 static hda_nid_t ad1988_dac_nids[4] = {
964 0x04, 0x06, 0x05, 0x0a
967 static hda_nid_t ad1988_adc_nids[3] = {
971 #define AD1988_SPDIF_OUT 0x02
972 #define AD1988_SPDIF_IN 0x07
974 static struct hda_input_mux ad1988_6stack_capture_source = {
977 { "Front Mic", 0x0 },
985 static struct hda_input_mux ad1988_laptop_capture_source = {
996 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
997 struct snd_ctl_elem_info *uinfo)
999 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1000 struct ad198x_spec *spec = codec->spec;
1001 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1002 spec->num_channel_mode);
1005 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1006 struct snd_ctl_elem_value *ucontrol)
1008 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1009 struct ad198x_spec *spec = codec->spec;
1010 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1011 spec->num_channel_mode, spec->multiout.max_channels);
1014 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1015 struct snd_ctl_elem_value *ucontrol)
1017 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1018 struct ad198x_spec *spec = codec->spec;
1019 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1020 spec->num_channel_mode, &spec->multiout.max_channels);
1026 static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
1027 struct snd_ctl_elem_info *uinfo)
1029 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1031 uinfo->value.integer.min = 0;
1032 uinfo->value.integer.max = 1;
1036 static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
1037 struct snd_ctl_elem_value *ucontrol)
1039 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1040 struct ad198x_spec *spec = codec->spec;
1041 ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
1045 static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
1046 struct snd_ctl_elem_value *ucontrol)
1048 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1049 struct ad198x_spec *spec = codec->spec;
1051 eapd = ! ucontrol->value.enumerated.item[0];
1052 if (eapd == spec->cur_eapd && ! codec->in_resume)
1054 spec->cur_eapd = eapd;
1055 snd_hda_codec_write(codec, 0x12 /* port-D */,
1056 0, AC_VERB_SET_EAPD_BTLENABLE,
1057 eapd ? 0x02 : 0x00);
1062 static struct snd_kcontrol_new ad1988_6stack_mixers[] = {
1063 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1064 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1065 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1066 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1067 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1069 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1070 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1071 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1072 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1073 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1074 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1075 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1077 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1078 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1079 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1080 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1081 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1082 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1083 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1084 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1086 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1087 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1089 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1090 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1092 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1093 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1099 static struct snd_kcontrol_new ad1988_3stack_mixers[] = {
1100 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1101 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1102 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1103 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1105 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1106 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1107 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1108 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1109 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1110 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1112 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1113 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1114 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1115 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1116 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1117 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1118 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1119 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1121 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1122 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1124 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1125 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1127 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1128 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1130 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1131 .name = "Channel Mode",
1132 .info = ad198x_ch_mode_info,
1133 .get = ad198x_ch_mode_get,
1134 .put = ad198x_ch_mode_put,
1141 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1142 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1143 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1144 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1146 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1147 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1148 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1149 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1150 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1151 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1153 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1154 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1156 HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1157 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1159 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1162 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1163 .name = "External Amplifier",
1164 .info = ad1988_eapd_info,
1165 .get = ad1988_eapd_get,
1166 .put = ad1988_eapd_put,
1173 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
1174 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
1175 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
1176 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
1177 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
1178 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
1179 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
1181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1182 /* The multiple "Capture Source" controls confuse alsamixer
1183 * So call somewhat different..
1184 * FIXME: the controls appear in the "playback" view!
1186 /* .name = "Capture Source", */
1187 .name = "Input Source",
1189 .info = ad198x_mux_enum_info,
1190 .get = ad198x_mux_enum_get,
1191 .put = ad198x_mux_enum_put,
1196 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
1197 struct snd_ctl_elem_info *uinfo)
1199 static char *texts[] = {
1200 "PCM", "ADC1", "ADC2", "ADC3"
1202 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1204 uinfo->value.enumerated.items = 4;
1205 if (uinfo->value.enumerated.item >= 4)
1206 uinfo->value.enumerated.item = 3;
1207 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1211 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
1212 struct snd_ctl_elem_value *ucontrol)
1214 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1217 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1219 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
1225 ucontrol->value.enumerated.item[0] = sel;
1229 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1230 struct snd_ctl_elem_value *ucontrol)
1232 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1236 sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1237 if (! ucontrol->value.enumerated.item[0]) {
1240 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
1244 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
1245 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
1246 change |= sel == ucontrol->value.enumerated.item[0];
1248 snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
1249 ucontrol->value.enumerated.item[0] - 1);
1254 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
1255 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1258 .name = "IEC958 Playback Source",
1259 .info = ad1988_spdif_playback_source_info,
1260 .get = ad1988_spdif_playback_source_get,
1261 .put = ad1988_spdif_playback_source_put,
1266 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
1267 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
1273 * initialization verbs
1277 * for 6-stack (+dig)
1279 static struct hda_verb ad1988_6stack_init_verbs[] = {
1280 /* Front, Surround, CLFE, side DAC; mute as default */
1281 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1282 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1283 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1284 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1285 /* Port-A front headphon path */
1286 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1287 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1288 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1289 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1290 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1291 /* Port-D line-out path */
1292 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1293 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1294 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1295 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1296 /* Port-F surround path */
1297 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1298 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1299 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1300 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1301 /* Port-G CLFE path */
1302 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1303 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1304 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1305 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1306 /* Port-H side path */
1307 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1308 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1309 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1310 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1312 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1313 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1314 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1315 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1316 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1317 /* Port-B front mic-in path */
1318 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1319 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1320 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1321 /* Port-C line-in path */
1322 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1323 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1324 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1325 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1326 /* Port-E mic-in path */
1327 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1328 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1329 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1330 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1335 static struct hda_verb ad1988_capture_init_verbs[] = {
1336 /* mute analog mix */
1337 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1338 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1339 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1340 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1341 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1342 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1343 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1344 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1345 /* select ADCs - front-mic */
1346 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1347 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1348 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1350 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1351 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1352 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1357 static struct hda_verb ad1988_spdif_init_verbs[] = {
1359 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
1360 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
1361 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1362 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1364 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
1365 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
1371 * verbs for 3stack (+dig)
1373 static struct hda_verb ad1988_3stack_ch2_init[] = {
1374 /* set port-C to line-in */
1375 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1376 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1377 /* set port-E to mic-in */
1378 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1379 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1383 static struct hda_verb ad1988_3stack_ch6_init[] = {
1384 /* set port-C to surround out */
1385 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1386 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1387 /* set port-E to CLFE out */
1388 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1389 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1393 static struct hda_channel_mode ad1988_3stack_modes[2] = {
1394 { 2, ad1988_3stack_ch2_init },
1395 { 6, ad1988_3stack_ch6_init },
1398 static struct hda_verb ad1988_3stack_init_verbs[] = {
1399 /* Front, Surround, CLFE, side DAC; mute as default */
1400 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1401 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1402 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1403 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1404 /* Port-A front headphon path */
1405 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1406 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1407 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1408 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1409 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1410 /* Port-D line-out path */
1411 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1412 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1413 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1414 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1416 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1417 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1418 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1419 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1420 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1421 /* Port-B front mic-in path */
1422 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1423 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1424 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1425 /* Port-C line-in/surround path */
1426 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1427 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1428 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1429 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1430 /* Port-E mic-in/CLFE path */
1431 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1432 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1433 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1434 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1435 /* mute analog mix */
1436 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1437 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1438 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1441 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1442 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1443 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1444 /* select ADCs - front-mic */
1445 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1446 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1447 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1449 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1450 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1451 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1456 * verbs for laptop mode (+dig)
1458 static struct hda_verb ad1988_laptop_hp_on[] = {
1459 /* unmute port-A and mute port-D */
1460 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1461 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1464 static struct hda_verb ad1988_laptop_hp_off[] = {
1465 /* mute port-A and unmute port-D */
1466 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1467 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1471 #define AD1988_HP_EVENT 0x01
1473 static struct hda_verb ad1988_laptop_init_verbs[] = {
1474 /* Front, Surround, CLFE, side DAC; mute as default */
1475 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1476 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1477 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1478 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1479 /* Port-A front headphon path */
1480 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1481 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1482 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1483 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1484 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1485 /* unsolicited event for pin-sense */
1486 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
1487 /* Port-D line-out path + EAPD */
1488 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1489 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1490 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1491 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1492 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
1494 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1495 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1496 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1497 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1498 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1499 /* Port-B mic-in path */
1500 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1501 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1502 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1503 /* Port-C docking station - try to output */
1504 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1505 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1506 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1507 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1508 /* mute analog mix */
1509 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1510 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1511 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1512 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1513 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1514 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1515 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1516 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1517 /* select ADCs - mic */
1518 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1519 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1520 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1522 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1523 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1524 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1528 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
1530 if ((res >> 26) != AD1988_HP_EVENT)
1532 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
1533 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
1535 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
1542 static struct hda_board_config ad1988_cfg_tbl[] = {
1543 { .modelname = "6stack", .config = AD1988_6STACK },
1544 { .modelname = "6stack-dig", .config = AD1988_6STACK_DIG },
1545 { .modelname = "3stack", .config = AD1988_3STACK },
1546 { .modelname = "3stack-dig", .config = AD1988_3STACK_DIG },
1547 { .modelname = "laptop", .config = AD1988_LAPTOP },
1548 { .modelname = "laptop-dig", .config = AD1988_LAPTOP_DIG },
1552 static int patch_ad1988(struct hda_codec *codec)
1554 struct ad198x_spec *spec;
1557 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1561 init_MUTEX(&spec->amp_mutex);
1564 board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
1565 if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
1566 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
1567 board_config = AD1988_6STACK;
1570 switch (board_config) {
1572 case AD1988_6STACK_DIG:
1573 spec->multiout.max_channels = 8;
1574 spec->multiout.num_dacs = 4;
1575 spec->multiout.dac_nids = ad1988_dac_nids;
1576 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1577 spec->adc_nids = ad1988_adc_nids;
1578 spec->input_mux = &ad1988_6stack_capture_source;
1579 spec->num_mixers = 1;
1580 spec->mixers[0] = ad1988_6stack_mixers;
1581 spec->num_init_verbs = 1;
1582 spec->init_verbs[0] = ad1988_6stack_init_verbs;
1583 if (board_config == AD1988_6STACK_DIG) {
1584 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1585 spec->dig_in_nid = AD1988_SPDIF_IN;
1589 case AD1988_3STACK_DIG:
1590 spec->multiout.max_channels = 6;
1591 spec->multiout.num_dacs = 3;
1592 spec->multiout.dac_nids = ad1988_dac_nids;
1593 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1594 spec->adc_nids = ad1988_adc_nids;
1595 spec->input_mux = &ad1988_6stack_capture_source;
1596 spec->channel_mode = ad1988_3stack_modes;
1597 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
1598 spec->num_mixers = 1;
1599 spec->mixers[0] = ad1988_3stack_mixers;
1600 spec->num_init_verbs = 1;
1601 spec->init_verbs[0] = ad1988_3stack_init_verbs;
1602 if (board_config == AD1988_3STACK_DIG)
1603 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1606 case AD1988_LAPTOP_DIG:
1607 spec->multiout.max_channels = 2;
1608 spec->multiout.num_dacs = 1;
1609 spec->multiout.dac_nids = ad1988_dac_nids;
1610 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1611 spec->adc_nids = ad1988_adc_nids;
1612 spec->input_mux = &ad1988_laptop_capture_source;
1613 spec->num_mixers = 1;
1614 spec->mixers[0] = ad1988_laptop_mixers;
1615 spec->num_init_verbs = 1;
1616 spec->init_verbs[0] = ad1988_laptop_init_verbs;
1617 if (board_config == AD1988_LAPTOP_DIG)
1618 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1622 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
1623 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
1624 if (spec->multiout.dig_out_nid) {
1625 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
1626 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
1628 if (spec->dig_in_nid)
1629 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
1631 codec->patch_ops = ad198x_patch_ops;
1632 switch (board_config) {
1634 case AD1988_LAPTOP_DIG:
1635 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
1646 struct hda_codec_preset snd_hda_preset_analog[] = {
1647 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
1648 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
1649 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
1650 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },