2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 struct snd_kcontrol_new
*mixers
[6];
35 unsigned int beep_amp
; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb
*init_verbs
[6]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs
;
42 struct hda_multi_out multiout
; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd
;
47 unsigned int need_dac_fix
;
49 hda_nid_t
*alt_dac_nid
;
50 struct hda_pcm_stream
*stream_analog_alt_playback
;
53 unsigned int num_adc_nids
;
55 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
58 const struct hda_input_mux
*input_mux
;
59 hda_nid_t
*capsrc_nids
;
60 unsigned int cur_mux
[3];
63 const struct hda_channel_mode
*channel_mode
;
67 struct hda_pcm pcm_rec
[3]; /* used in alc_build_pcms() */
69 unsigned int spdif_route
;
71 /* dynamic controls, init_verbs and input_mux */
72 struct auto_pin_cfg autocfg
;
73 struct snd_array kctls
;
74 struct hda_input_mux private_imux
;
75 hda_nid_t private_dac_nids
[AUTO_CFG_MAX_OUTS
];
77 unsigned int jack_present
: 1;
78 unsigned int inv_jack_detect
: 1;/* inverted jack-detection */
79 unsigned int inv_eapd
: 1; /* inverted EAPD implementation */
80 unsigned int analog_beep
: 1; /* analog beep input present */
82 #ifdef CONFIG_SND_HDA_POWER_SAVE
83 struct hda_loopback_check loopback
;
85 /* for virtual master */
86 hda_nid_t vmaster_nid
;
87 const char * const *slave_vols
;
88 const char * const *slave_sws
;
92 * input MUX handling (common part)
94 static int ad198x_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
96 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
97 struct ad198x_spec
*spec
= codec
->spec
;
99 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
102 static int ad198x_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
104 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
105 struct ad198x_spec
*spec
= codec
->spec
;
106 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
108 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
112 static int ad198x_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
114 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
115 struct ad198x_spec
*spec
= codec
->spec
;
116 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
118 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
119 spec
->capsrc_nids
[adc_idx
],
120 &spec
->cur_mux
[adc_idx
]);
124 * initialization (common callbacks)
126 static int ad198x_init(struct hda_codec
*codec
)
128 struct ad198x_spec
*spec
= codec
->spec
;
131 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
132 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
136 static const char * const ad_slave_vols
[] = {
137 "Front Playback Volume",
138 "Surround Playback Volume",
139 "Center Playback Volume",
140 "LFE Playback Volume",
141 "Side Playback Volume",
142 "Headphone Playback Volume",
143 "Mono Playback Volume",
144 "Speaker Playback Volume",
145 "IEC958 Playback Volume",
149 static const char * const ad_slave_sws
[] = {
150 "Front Playback Switch",
151 "Surround Playback Switch",
152 "Center Playback Switch",
153 "LFE Playback Switch",
154 "Side Playback Switch",
155 "Headphone Playback Switch",
156 "Mono Playback Switch",
157 "Speaker Playback Switch",
158 "IEC958 Playback Switch",
162 static const char * const ad1988_6stack_fp_slave_vols
[] = {
163 "Front Playback Volume",
164 "Surround Playback Volume",
165 "Center Playback Volume",
166 "LFE Playback Volume",
167 "Side Playback Volume",
168 "IEC958 Playback Volume",
172 static const char * const ad1988_6stack_fp_slave_sws
[] = {
173 "Front Playback Switch",
174 "Surround Playback Switch",
175 "Center Playback Switch",
176 "LFE Playback Switch",
177 "Side Playback Switch",
178 "IEC958 Playback Switch",
181 static void ad198x_free_kctls(struct hda_codec
*codec
);
183 #ifdef CONFIG_SND_HDA_INPUT_BEEP
184 /* additional beep mixers; the actual parameters are overwritten at build */
185 static struct snd_kcontrol_new ad_beep_mixer
[] = {
186 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT
),
187 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT
),
191 static struct snd_kcontrol_new ad_beep2_mixer
[] = {
192 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT
),
193 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT
),
197 #define set_beep_amp(spec, nid, idx, dir) \
198 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
200 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
203 static int ad198x_build_controls(struct hda_codec
*codec
)
205 struct ad198x_spec
*spec
= codec
->spec
;
206 struct snd_kcontrol
*kctl
;
210 for (i
= 0; i
< spec
->num_mixers
; i
++) {
211 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
215 if (spec
->multiout
.dig_out_nid
) {
216 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
219 err
= snd_hda_create_spdif_share_sw(codec
,
223 spec
->multiout
.share_spdif
= 1;
225 if (spec
->dig_in_nid
) {
226 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
231 /* create beep controls if needed */
232 #ifdef CONFIG_SND_HDA_INPUT_BEEP
233 if (spec
->beep_amp
) {
234 struct snd_kcontrol_new
*knew
;
235 knew
= spec
->analog_beep
? ad_beep2_mixer
: ad_beep_mixer
;
236 for ( ; knew
->name
; knew
++) {
237 struct snd_kcontrol
*kctl
;
238 kctl
= snd_ctl_new1(knew
, codec
);
241 kctl
->private_value
= spec
->beep_amp
;
242 err
= snd_hda_ctl_add(codec
, 0, kctl
);
249 /* if we have no master control, let's create it */
250 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Volume")) {
251 unsigned int vmaster_tlv
[4];
252 snd_hda_set_vmaster_tlv(codec
, spec
->vmaster_nid
,
253 HDA_OUTPUT
, vmaster_tlv
);
254 err
= snd_hda_add_vmaster(codec
, "Master Playback Volume",
257 spec
->slave_vols
: ad_slave_vols
));
261 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Switch")) {
262 err
= snd_hda_add_vmaster(codec
, "Master Playback Switch",
265 spec
->slave_sws
: ad_slave_sws
));
270 ad198x_free_kctls(codec
); /* no longer needed */
272 /* assign Capture Source enums to NID */
273 kctl
= snd_hda_find_mixer_ctl(codec
, "Capture Source");
275 kctl
= snd_hda_find_mixer_ctl(codec
, "Input Source");
276 for (i
= 0; kctl
&& i
< kctl
->count
; i
++) {
277 err
= snd_hda_add_nid(codec
, kctl
, i
, spec
->capsrc_nids
[i
]);
282 /* assign IEC958 enums to NID */
283 kctl
= snd_hda_find_mixer_ctl(codec
,
284 SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source");
286 err
= snd_hda_add_nid(codec
, kctl
, 0,
287 spec
->multiout
.dig_out_nid
);
295 #ifdef CONFIG_SND_HDA_POWER_SAVE
296 static int ad198x_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
298 struct ad198x_spec
*spec
= codec
->spec
;
299 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
304 * Analog playback callbacks
306 static int ad198x_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
307 struct hda_codec
*codec
,
308 struct snd_pcm_substream
*substream
)
310 struct ad198x_spec
*spec
= codec
->spec
;
311 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
315 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
316 struct hda_codec
*codec
,
317 unsigned int stream_tag
,
319 struct snd_pcm_substream
*substream
)
321 struct ad198x_spec
*spec
= codec
->spec
;
322 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
326 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
327 struct hda_codec
*codec
,
328 struct snd_pcm_substream
*substream
)
330 struct ad198x_spec
*spec
= codec
->spec
;
331 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
334 static struct hda_pcm_stream ad198x_pcm_analog_alt_playback
= {
338 /* NID is set in ad198x_build_pcms */
344 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
345 struct hda_codec
*codec
,
346 struct snd_pcm_substream
*substream
)
348 struct ad198x_spec
*spec
= codec
->spec
;
349 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
352 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
353 struct hda_codec
*codec
,
354 struct snd_pcm_substream
*substream
)
356 struct ad198x_spec
*spec
= codec
->spec
;
357 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
360 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
361 struct hda_codec
*codec
,
362 unsigned int stream_tag
,
364 struct snd_pcm_substream
*substream
)
366 struct ad198x_spec
*spec
= codec
->spec
;
367 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
371 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
372 struct hda_codec
*codec
,
373 struct snd_pcm_substream
*substream
)
375 struct ad198x_spec
*spec
= codec
->spec
;
376 return snd_hda_multi_out_dig_cleanup(codec
, &spec
->multiout
);
382 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
383 struct hda_codec
*codec
,
384 unsigned int stream_tag
,
386 struct snd_pcm_substream
*substream
)
388 struct ad198x_spec
*spec
= codec
->spec
;
389 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
390 stream_tag
, 0, format
);
394 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
395 struct hda_codec
*codec
,
396 struct snd_pcm_substream
*substream
)
398 struct ad198x_spec
*spec
= codec
->spec
;
399 snd_hda_codec_cleanup_stream(codec
, spec
->adc_nids
[substream
->number
]);
406 static struct hda_pcm_stream ad198x_pcm_analog_playback
= {
409 .channels_max
= 6, /* changed later */
410 .nid
= 0, /* fill later */
412 .open
= ad198x_playback_pcm_open
,
413 .prepare
= ad198x_playback_pcm_prepare
,
414 .cleanup
= ad198x_playback_pcm_cleanup
418 static struct hda_pcm_stream ad198x_pcm_analog_capture
= {
422 .nid
= 0, /* fill later */
424 .prepare
= ad198x_capture_pcm_prepare
,
425 .cleanup
= ad198x_capture_pcm_cleanup
429 static struct hda_pcm_stream ad198x_pcm_digital_playback
= {
433 .nid
= 0, /* fill later */
435 .open
= ad198x_dig_playback_pcm_open
,
436 .close
= ad198x_dig_playback_pcm_close
,
437 .prepare
= ad198x_dig_playback_pcm_prepare
,
438 .cleanup
= ad198x_dig_playback_pcm_cleanup
442 static struct hda_pcm_stream ad198x_pcm_digital_capture
= {
446 /* NID is set in alc_build_pcms */
449 static int ad198x_build_pcms(struct hda_codec
*codec
)
451 struct ad198x_spec
*spec
= codec
->spec
;
452 struct hda_pcm
*info
= spec
->pcm_rec
;
455 codec
->pcm_info
= info
;
457 info
->name
= "AD198x Analog";
458 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_analog_playback
;
459 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->multiout
.max_channels
;
460 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
461 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_analog_capture
;
462 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_adc_nids
;
463 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
465 if (spec
->multiout
.dig_out_nid
) {
468 info
->name
= "AD198x Digital";
469 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
470 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_digital_playback
;
471 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
472 if (spec
->dig_in_nid
) {
473 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_digital_capture
;
474 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
478 if (spec
->alt_dac_nid
&& spec
->stream_analog_alt_playback
) {
480 info
= spec
->pcm_rec
+ 2;
481 info
->name
= "AD198x Headphone";
482 info
->pcm_type
= HDA_PCM_TYPE_AUDIO
;
483 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
484 *spec
->stream_analog_alt_playback
;
485 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
486 spec
->alt_dac_nid
[0];
492 static inline void ad198x_shutup(struct hda_codec
*codec
)
494 snd_hda_shutup_pins(codec
);
497 static void ad198x_free_kctls(struct hda_codec
*codec
)
499 struct ad198x_spec
*spec
= codec
->spec
;
501 if (spec
->kctls
.list
) {
502 struct snd_kcontrol_new
*kctl
= spec
->kctls
.list
;
504 for (i
= 0; i
< spec
->kctls
.used
; i
++)
507 snd_array_free(&spec
->kctls
);
510 static void ad198x_power_eapd_write(struct hda_codec
*codec
, hda_nid_t front
,
513 struct ad198x_spec
*spec
= codec
->spec
;
514 snd_hda_codec_write(codec
, front
, 0, AC_VERB_SET_EAPD_BTLENABLE
,
515 !spec
->inv_eapd
? 0x00 : 0x02);
516 snd_hda_codec_write(codec
, hp
, 0, AC_VERB_SET_EAPD_BTLENABLE
,
517 !spec
->inv_eapd
? 0x00 : 0x02);
520 static void ad198x_power_eapd(struct hda_codec
*codec
)
522 /* We currently only handle front, HP */
523 switch (codec
->vendor_id
) {
532 ad198x_power_eapd_write(codec
, 0x12, 0x11);
536 ad198x_power_eapd_write(codec
, 0x05, 0x06);
539 ad198x_power_eapd_write(codec
, 0x1b, 0x1a);
545 ad198x_power_eapd_write(codec
, 0x29, 0x22);
550 static void ad198x_free(struct hda_codec
*codec
)
552 struct ad198x_spec
*spec
= codec
->spec
;
557 ad198x_shutup(codec
);
558 ad198x_free_kctls(codec
);
560 snd_hda_detach_beep_device(codec
);
563 #ifdef SND_HDA_NEEDS_RESUME
564 static int ad198x_suspend(struct hda_codec
*codec
, pm_message_t state
)
566 ad198x_shutup(codec
);
567 ad198x_power_eapd(codec
);
572 static struct hda_codec_ops ad198x_patch_ops
= {
573 .build_controls
= ad198x_build_controls
,
574 .build_pcms
= ad198x_build_pcms
,
577 #ifdef CONFIG_SND_HDA_POWER_SAVE
578 .check_power_status
= ad198x_check_power_status
,
580 #ifdef SND_HDA_NEEDS_RESUME
581 .suspend
= ad198x_suspend
,
583 .reboot_notify
= ad198x_shutup
,
589 * the private value = nid
591 #define ad198x_eapd_info snd_ctl_boolean_mono_info
593 static int ad198x_eapd_get(struct snd_kcontrol
*kcontrol
,
594 struct snd_ctl_elem_value
*ucontrol
)
596 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
597 struct ad198x_spec
*spec
= codec
->spec
;
599 ucontrol
->value
.integer
.value
[0] = ! spec
->cur_eapd
;
601 ucontrol
->value
.integer
.value
[0] = spec
->cur_eapd
;
605 static int ad198x_eapd_put(struct snd_kcontrol
*kcontrol
,
606 struct snd_ctl_elem_value
*ucontrol
)
608 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
609 struct ad198x_spec
*spec
= codec
->spec
;
610 hda_nid_t nid
= kcontrol
->private_value
& 0xff;
612 eapd
= !!ucontrol
->value
.integer
.value
[0];
615 if (eapd
== spec
->cur_eapd
)
617 spec
->cur_eapd
= eapd
;
618 snd_hda_codec_write_cache(codec
, nid
,
619 0, AC_VERB_SET_EAPD_BTLENABLE
,
624 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
625 struct snd_ctl_elem_info
*uinfo
);
626 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
627 struct snd_ctl_elem_value
*ucontrol
);
628 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
629 struct snd_ctl_elem_value
*ucontrol
);
636 #define AD1986A_SPDIF_OUT 0x02
637 #define AD1986A_FRONT_DAC 0x03
638 #define AD1986A_SURR_DAC 0x04
639 #define AD1986A_CLFE_DAC 0x05
640 #define AD1986A_ADC 0x06
642 static hda_nid_t ad1986a_dac_nids
[3] = {
643 AD1986A_FRONT_DAC
, AD1986A_SURR_DAC
, AD1986A_CLFE_DAC
645 static hda_nid_t ad1986a_adc_nids
[1] = { AD1986A_ADC
};
646 static hda_nid_t ad1986a_capsrc_nids
[1] = { 0x12 };
648 static struct hda_input_mux ad1986a_capture_source
= {
662 static struct hda_bind_ctls ad1986a_bind_pcm_vol
= {
663 .ops
= &snd_hda_bind_vol
,
665 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
666 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
667 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
672 static struct hda_bind_ctls ad1986a_bind_pcm_sw
= {
673 .ops
= &snd_hda_bind_sw
,
675 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
676 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
677 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
685 static struct snd_kcontrol_new ad1986a_mixers
[] = {
687 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
689 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol
),
690 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw
),
691 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
692 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
693 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
694 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
695 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT
),
696 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT
),
697 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT
),
698 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT
),
699 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT
),
700 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT
),
701 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
702 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
703 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
704 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
705 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
706 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
707 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
708 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
709 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
710 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT
),
711 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT
),
712 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
713 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
715 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
716 .name
= "Capture Source",
717 .info
= ad198x_mux_enum_info
,
718 .get
= ad198x_mux_enum_get
,
719 .put
= ad198x_mux_enum_put
,
721 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT
),
725 /* additional mixers for 3stack mode */
726 static struct snd_kcontrol_new ad1986a_3st_mixers
[] = {
728 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
729 .name
= "Channel Mode",
730 .info
= ad198x_ch_mode_info
,
731 .get
= ad198x_ch_mode_get
,
732 .put
= ad198x_ch_mode_put
,
737 /* laptop model - 2ch only */
738 static hda_nid_t ad1986a_laptop_dac_nids
[1] = { AD1986A_FRONT_DAC
};
740 /* master controls both pins 0x1a and 0x1b */
741 static struct hda_bind_ctls ad1986a_laptop_master_vol
= {
742 .ops
= &snd_hda_bind_vol
,
744 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
745 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
750 static struct hda_bind_ctls ad1986a_laptop_master_sw
= {
751 .ops
= &snd_hda_bind_sw
,
753 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
754 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
759 static struct snd_kcontrol_new ad1986a_laptop_mixers
[] = {
760 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
761 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
762 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
763 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
764 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
765 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
766 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
767 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
768 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
769 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
770 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
771 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
772 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
774 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
775 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
776 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
777 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
779 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
780 .name
= "Capture Source",
781 .info
= ad198x_mux_enum_info
,
782 .get
= ad198x_mux_enum_get
,
783 .put
= ad198x_mux_enum_put
,
788 /* laptop-eapd model - 2ch only */
790 static struct hda_input_mux ad1986a_laptop_eapd_capture_source
= {
794 { "Internal Mic", 0x4 },
799 static struct hda_input_mux ad1986a_automic_capture_source
= {
807 static struct snd_kcontrol_new ad1986a_laptop_master_mixers
[] = {
808 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
809 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
813 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers
[] = {
814 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
815 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
816 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
817 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
818 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
819 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
820 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
822 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
823 .name
= "Capture Source",
824 .info
= ad198x_mux_enum_info
,
825 .get
= ad198x_mux_enum_get
,
826 .put
= ad198x_mux_enum_put
,
829 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
830 .name
= "External Amplifier",
831 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x1b,
832 .info
= ad198x_eapd_info
,
833 .get
= ad198x_eapd_get
,
834 .put
= ad198x_eapd_put
,
835 .private_value
= 0x1b, /* port-D */
840 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers
[] = {
841 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT
),
842 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT
),
846 /* re-connect the mic boost input according to the jack sensing */
847 static void ad1986a_automic(struct hda_codec
*codec
)
849 unsigned int present
;
850 present
= snd_hda_jack_detect(codec
, 0x1f);
851 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
852 snd_hda_codec_write(codec
, 0x0f, 0, AC_VERB_SET_CONNECT_SEL
,
856 #define AD1986A_MIC_EVENT 0x36
858 static void ad1986a_automic_unsol_event(struct hda_codec
*codec
,
861 if ((res
>> 26) != AD1986A_MIC_EVENT
)
863 ad1986a_automic(codec
);
866 static int ad1986a_automic_init(struct hda_codec
*codec
)
869 ad1986a_automic(codec
);
873 /* laptop-automute - 2ch only */
875 static void ad1986a_update_hp(struct hda_codec
*codec
)
877 struct ad198x_spec
*spec
= codec
->spec
;
880 if (spec
->jack_present
)
881 mute
= HDA_AMP_MUTE
; /* mute internal speaker */
883 /* unmute internal speaker if necessary */
884 mute
= snd_hda_codec_amp_read(codec
, 0x1a, 0, HDA_OUTPUT
, 0);
885 snd_hda_codec_amp_stereo(codec
, 0x1b, HDA_OUTPUT
, 0,
889 static void ad1986a_hp_automute(struct hda_codec
*codec
)
891 struct ad198x_spec
*spec
= codec
->spec
;
893 spec
->jack_present
= snd_hda_jack_detect(codec
, 0x1a);
894 if (spec
->inv_jack_detect
)
895 spec
->jack_present
= !spec
->jack_present
;
896 ad1986a_update_hp(codec
);
899 #define AD1986A_HP_EVENT 0x37
901 static void ad1986a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
903 if ((res
>> 26) != AD1986A_HP_EVENT
)
905 ad1986a_hp_automute(codec
);
908 static int ad1986a_hp_init(struct hda_codec
*codec
)
911 ad1986a_hp_automute(codec
);
915 /* bind hp and internal speaker mute (with plug check) */
916 static int ad1986a_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
917 struct snd_ctl_elem_value
*ucontrol
)
919 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
920 long *valp
= ucontrol
->value
.integer
.value
;
923 change
= snd_hda_codec_amp_update(codec
, 0x1a, 0, HDA_OUTPUT
, 0,
925 valp
[0] ? 0 : HDA_AMP_MUTE
);
926 change
|= snd_hda_codec_amp_update(codec
, 0x1a, 1, HDA_OUTPUT
, 0,
928 valp
[1] ? 0 : HDA_AMP_MUTE
);
930 ad1986a_update_hp(codec
);
934 static struct snd_kcontrol_new ad1986a_automute_master_mixers
[] = {
935 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
937 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
938 .name
= "Master Playback Switch",
939 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
940 .info
= snd_hda_mixer_amp_switch_info
,
941 .get
= snd_hda_mixer_amp_switch_get
,
942 .put
= ad1986a_hp_master_sw_put
,
943 .private_value
= HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
950 * initialization verbs
952 static struct hda_verb ad1986a_init_verbs
[] = {
953 /* Front, Surround, CLFE DAC; mute as default */
954 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
955 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
956 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
958 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
959 /* HP, Line-Out, Surround, CLFE selectors */
960 {0x0a, AC_VERB_SET_CONNECT_SEL
, 0x0},
961 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0},
962 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
963 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
965 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x0},
966 /* Mic selector: Mic 1/2 pin */
967 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
968 /* Line-in selector: Line-in */
969 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x0},
971 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x0},
972 /* Record selector: mic */
973 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x0},
974 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
975 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
976 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
977 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
978 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
979 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
981 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x0},
982 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
983 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
984 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
985 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
986 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
987 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
989 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
990 /* Front, Surround, CLFE Pins */
991 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
992 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
993 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
995 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
997 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
998 /* Line, Aux, CD, Beep-In Pin */
999 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1000 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1001 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1002 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1003 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1007 static struct hda_verb ad1986a_ch2_init
[] = {
1008 /* Surround out -> Line In */
1009 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1010 /* Line-in selectors */
1011 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x1 },
1012 /* CLFE -> Mic in */
1013 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1014 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1015 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
1019 static struct hda_verb ad1986a_ch4_init
[] = {
1020 /* Surround out -> Surround */
1021 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1022 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1023 /* CLFE -> Mic in */
1024 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1025 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
1029 static struct hda_verb ad1986a_ch6_init
[] = {
1030 /* Surround out -> Surround out */
1031 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1032 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1034 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1035 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1039 static struct hda_channel_mode ad1986a_modes
[3] = {
1040 { 2, ad1986a_ch2_init
},
1041 { 4, ad1986a_ch4_init
},
1042 { 6, ad1986a_ch6_init
},
1045 /* eapd initialization */
1046 static struct hda_verb ad1986a_eapd_init_verbs
[] = {
1047 {0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
1051 static struct hda_verb ad1986a_automic_verbs
[] = {
1052 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1053 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1054 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1055 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
1056 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_MIC_EVENT
},
1060 /* Ultra initialization */
1061 static struct hda_verb ad1986a_ultra_init
[] = {
1062 /* eapd initialization */
1063 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
1064 /* CLFE -> Mic in */
1065 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x2 },
1066 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1067 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
1071 /* pin sensing on HP jack */
1072 static struct hda_verb ad1986a_hp_init_verbs
[] = {
1073 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_HP_EVENT
},
1077 static void ad1986a_samsung_p50_unsol_event(struct hda_codec
*codec
,
1080 switch (res
>> 26) {
1081 case AD1986A_HP_EVENT
:
1082 ad1986a_hp_automute(codec
);
1084 case AD1986A_MIC_EVENT
:
1085 ad1986a_automic(codec
);
1090 static int ad1986a_samsung_p50_init(struct hda_codec
*codec
)
1093 ad1986a_hp_automute(codec
);
1094 ad1986a_automic(codec
);
1104 AD1986A_LAPTOP_EAPD
,
1105 AD1986A_LAPTOP_AUTOMUTE
,
1108 AD1986A_SAMSUNG_P50
,
1112 static const char * const ad1986a_models
[AD1986A_MODELS
] = {
1113 [AD1986A_6STACK
] = "6stack",
1114 [AD1986A_3STACK
] = "3stack",
1115 [AD1986A_LAPTOP
] = "laptop",
1116 [AD1986A_LAPTOP_EAPD
] = "laptop-eapd",
1117 [AD1986A_LAPTOP_AUTOMUTE
] = "laptop-automute",
1118 [AD1986A_ULTRA
] = "ultra",
1119 [AD1986A_SAMSUNG
] = "samsung",
1120 [AD1986A_SAMSUNG_P50
] = "samsung-p50",
1123 static struct snd_pci_quirk ad1986a_cfg_tbl
[] = {
1124 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD
),
1125 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD
),
1126 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD
),
1127 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD
),
1128 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD
),
1129 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD
),
1130 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD
),
1131 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD
),
1132 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP
),
1133 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK
),
1134 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK
),
1135 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP
),
1136 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK
),
1137 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK
),
1138 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK
),
1139 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK
),
1140 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK
),
1141 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK
),
1142 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP
),
1143 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50
),
1144 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA
),
1145 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG
),
1146 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK
),
1147 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP
),
1148 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK
),
1149 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE
),
1150 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP
),
1154 #ifdef CONFIG_SND_HDA_POWER_SAVE
1155 static struct hda_amp_list ad1986a_loopbacks
[] = {
1156 { 0x13, HDA_OUTPUT
, 0 }, /* Mic */
1157 { 0x14, HDA_OUTPUT
, 0 }, /* Phone */
1158 { 0x15, HDA_OUTPUT
, 0 }, /* CD */
1159 { 0x16, HDA_OUTPUT
, 0 }, /* Aux */
1160 { 0x17, HDA_OUTPUT
, 0 }, /* Line */
1165 static int is_jack_available(struct hda_codec
*codec
, hda_nid_t nid
)
1167 unsigned int conf
= snd_hda_codec_get_pincfg(codec
, nid
);
1168 return get_defcfg_connect(conf
) != AC_JACK_PORT_NONE
;
1171 static int patch_ad1986a(struct hda_codec
*codec
)
1173 struct ad198x_spec
*spec
;
1174 int err
, board_config
;
1176 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1182 err
= snd_hda_attach_beep_device(codec
, 0x19);
1187 set_beep_amp(spec
, 0x18, 0, HDA_OUTPUT
);
1189 spec
->multiout
.max_channels
= 6;
1190 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1986a_dac_nids
);
1191 spec
->multiout
.dac_nids
= ad1986a_dac_nids
;
1192 spec
->multiout
.dig_out_nid
= AD1986A_SPDIF_OUT
;
1193 spec
->num_adc_nids
= 1;
1194 spec
->adc_nids
= ad1986a_adc_nids
;
1195 spec
->capsrc_nids
= ad1986a_capsrc_nids
;
1196 spec
->input_mux
= &ad1986a_capture_source
;
1197 spec
->num_mixers
= 1;
1198 spec
->mixers
[0] = ad1986a_mixers
;
1199 spec
->num_init_verbs
= 1;
1200 spec
->init_verbs
[0] = ad1986a_init_verbs
;
1201 #ifdef CONFIG_SND_HDA_POWER_SAVE
1202 spec
->loopback
.amplist
= ad1986a_loopbacks
;
1204 spec
->vmaster_nid
= 0x1b;
1205 spec
->inv_eapd
= 1; /* AD1986A has the inverted EAPD implementation */
1207 codec
->patch_ops
= ad198x_patch_ops
;
1209 /* override some parameters */
1210 board_config
= snd_hda_check_board_config(codec
, AD1986A_MODELS
,
1213 switch (board_config
) {
1214 case AD1986A_3STACK
:
1215 spec
->num_mixers
= 2;
1216 spec
->mixers
[1] = ad1986a_3st_mixers
;
1217 spec
->num_init_verbs
= 2;
1218 spec
->init_verbs
[1] = ad1986a_ch2_init
;
1219 spec
->channel_mode
= ad1986a_modes
;
1220 spec
->num_channel_mode
= ARRAY_SIZE(ad1986a_modes
);
1221 spec
->need_dac_fix
= 1;
1222 spec
->multiout
.max_channels
= 2;
1223 spec
->multiout
.num_dacs
= 1;
1225 case AD1986A_LAPTOP
:
1226 spec
->mixers
[0] = ad1986a_laptop_mixers
;
1227 spec
->multiout
.max_channels
= 2;
1228 spec
->multiout
.num_dacs
= 1;
1229 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1231 case AD1986A_LAPTOP_EAPD
:
1232 spec
->num_mixers
= 3;
1233 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1234 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1235 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1236 spec
->num_init_verbs
= 2;
1237 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1238 spec
->multiout
.max_channels
= 2;
1239 spec
->multiout
.num_dacs
= 1;
1240 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1241 if (!is_jack_available(codec
, 0x25))
1242 spec
->multiout
.dig_out_nid
= 0;
1243 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1245 case AD1986A_SAMSUNG
:
1246 spec
->num_mixers
= 2;
1247 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1248 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1249 spec
->num_init_verbs
= 3;
1250 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1251 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1252 spec
->multiout
.max_channels
= 2;
1253 spec
->multiout
.num_dacs
= 1;
1254 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1255 if (!is_jack_available(codec
, 0x25))
1256 spec
->multiout
.dig_out_nid
= 0;
1257 spec
->input_mux
= &ad1986a_automic_capture_source
;
1258 codec
->patch_ops
.unsol_event
= ad1986a_automic_unsol_event
;
1259 codec
->patch_ops
.init
= ad1986a_automic_init
;
1261 case AD1986A_SAMSUNG_P50
:
1262 spec
->num_mixers
= 2;
1263 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1264 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1265 spec
->num_init_verbs
= 4;
1266 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1267 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1268 spec
->init_verbs
[3] = ad1986a_hp_init_verbs
;
1269 spec
->multiout
.max_channels
= 2;
1270 spec
->multiout
.num_dacs
= 1;
1271 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1272 if (!is_jack_available(codec
, 0x25))
1273 spec
->multiout
.dig_out_nid
= 0;
1274 spec
->input_mux
= &ad1986a_automic_capture_source
;
1275 codec
->patch_ops
.unsol_event
= ad1986a_samsung_p50_unsol_event
;
1276 codec
->patch_ops
.init
= ad1986a_samsung_p50_init
;
1278 case AD1986A_LAPTOP_AUTOMUTE
:
1279 spec
->num_mixers
= 3;
1280 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1281 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1282 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1283 spec
->num_init_verbs
= 3;
1284 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1285 spec
->init_verbs
[2] = ad1986a_hp_init_verbs
;
1286 spec
->multiout
.max_channels
= 2;
1287 spec
->multiout
.num_dacs
= 1;
1288 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1289 if (!is_jack_available(codec
, 0x25))
1290 spec
->multiout
.dig_out_nid
= 0;
1291 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1292 codec
->patch_ops
.unsol_event
= ad1986a_hp_unsol_event
;
1293 codec
->patch_ops
.init
= ad1986a_hp_init
;
1294 /* Lenovo N100 seems to report the reversed bit
1295 * for HP jack-sensing
1297 spec
->inv_jack_detect
= 1;
1300 spec
->mixers
[0] = ad1986a_laptop_eapd_mixers
;
1301 spec
->num_init_verbs
= 2;
1302 spec
->init_verbs
[1] = ad1986a_ultra_init
;
1303 spec
->multiout
.max_channels
= 2;
1304 spec
->multiout
.num_dacs
= 1;
1305 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1306 spec
->multiout
.dig_out_nid
= 0;
1310 /* AD1986A has a hardware problem that it can't share a stream
1311 * with multiple output pins. The copy of front to surrounds
1312 * causes noisy or silent outputs at a certain timing, e.g.
1313 * changing the volume.
1314 * So, let's disable the shared stream.
1316 spec
->multiout
.no_share_stream
= 1;
1318 codec
->no_trigger_sense
= 1;
1319 codec
->no_sticky_stream
= 1;
1328 #define AD1983_SPDIF_OUT 0x02
1329 #define AD1983_DAC 0x03
1330 #define AD1983_ADC 0x04
1332 static hda_nid_t ad1983_dac_nids
[1] = { AD1983_DAC
};
1333 static hda_nid_t ad1983_adc_nids
[1] = { AD1983_ADC
};
1334 static hda_nid_t ad1983_capsrc_nids
[1] = { 0x15 };
1336 static struct hda_input_mux ad1983_capture_source
= {
1342 { "Mix Mono", 0x3 },
1347 * SPDIF playback route
1349 static int ad1983_spdif_route_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1351 static char *texts
[] = { "PCM", "ADC" };
1353 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1355 uinfo
->value
.enumerated
.items
= 2;
1356 if (uinfo
->value
.enumerated
.item
> 1)
1357 uinfo
->value
.enumerated
.item
= 1;
1358 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1362 static int ad1983_spdif_route_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1364 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1365 struct ad198x_spec
*spec
= codec
->spec
;
1367 ucontrol
->value
.enumerated
.item
[0] = spec
->spdif_route
;
1371 static int ad1983_spdif_route_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1373 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1374 struct ad198x_spec
*spec
= codec
->spec
;
1376 if (ucontrol
->value
.enumerated
.item
[0] > 1)
1378 if (spec
->spdif_route
!= ucontrol
->value
.enumerated
.item
[0]) {
1379 spec
->spdif_route
= ucontrol
->value
.enumerated
.item
[0];
1380 snd_hda_codec_write_cache(codec
, spec
->multiout
.dig_out_nid
, 0,
1381 AC_VERB_SET_CONNECT_SEL
,
1388 static struct snd_kcontrol_new ad1983_mixers
[] = {
1389 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1390 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1391 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1392 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1393 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1394 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1395 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1396 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1397 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1398 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1399 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1400 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1401 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT
),
1402 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1403 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1405 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1406 .name
= "Capture Source",
1407 .info
= ad198x_mux_enum_info
,
1408 .get
= ad198x_mux_enum_get
,
1409 .put
= ad198x_mux_enum_put
,
1412 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1413 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1414 .info
= ad1983_spdif_route_info
,
1415 .get
= ad1983_spdif_route_get
,
1416 .put
= ad1983_spdif_route_put
,
1421 static struct hda_verb ad1983_init_verbs
[] = {
1422 /* Front, HP, Mono; mute as default */
1423 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1424 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1425 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1426 /* Beep, PCM, Mic, Line-In: mute */
1427 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1428 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1429 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1430 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1431 /* Front, HP selectors; from Mix */
1432 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1433 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1434 /* Mono selector; from Mix */
1435 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1436 /* Mic selector; Mic */
1437 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
1438 /* Line-in selector: Line-in */
1439 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1440 /* Mic boost: 0dB */
1441 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1442 /* Record selector: mic */
1443 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1444 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1445 /* SPDIF route: PCM */
1446 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1448 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1450 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1452 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1454 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1456 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1460 #ifdef CONFIG_SND_HDA_POWER_SAVE
1461 static struct hda_amp_list ad1983_loopbacks
[] = {
1462 { 0x12, HDA_OUTPUT
, 0 }, /* Mic */
1463 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1468 static int patch_ad1983(struct hda_codec
*codec
)
1470 struct ad198x_spec
*spec
;
1473 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1479 err
= snd_hda_attach_beep_device(codec
, 0x10);
1484 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
1486 spec
->multiout
.max_channels
= 2;
1487 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1983_dac_nids
);
1488 spec
->multiout
.dac_nids
= ad1983_dac_nids
;
1489 spec
->multiout
.dig_out_nid
= AD1983_SPDIF_OUT
;
1490 spec
->num_adc_nids
= 1;
1491 spec
->adc_nids
= ad1983_adc_nids
;
1492 spec
->capsrc_nids
= ad1983_capsrc_nids
;
1493 spec
->input_mux
= &ad1983_capture_source
;
1494 spec
->num_mixers
= 1;
1495 spec
->mixers
[0] = ad1983_mixers
;
1496 spec
->num_init_verbs
= 1;
1497 spec
->init_verbs
[0] = ad1983_init_verbs
;
1498 spec
->spdif_route
= 0;
1499 #ifdef CONFIG_SND_HDA_POWER_SAVE
1500 spec
->loopback
.amplist
= ad1983_loopbacks
;
1502 spec
->vmaster_nid
= 0x05;
1504 codec
->patch_ops
= ad198x_patch_ops
;
1506 codec
->no_trigger_sense
= 1;
1507 codec
->no_sticky_stream
= 1;
1514 * AD1981 HD specific
1517 #define AD1981_SPDIF_OUT 0x02
1518 #define AD1981_DAC 0x03
1519 #define AD1981_ADC 0x04
1521 static hda_nid_t ad1981_dac_nids
[1] = { AD1981_DAC
};
1522 static hda_nid_t ad1981_adc_nids
[1] = { AD1981_ADC
};
1523 static hda_nid_t ad1981_capsrc_nids
[1] = { 0x15 };
1525 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1526 static struct hda_input_mux ad1981_capture_source
= {
1529 { "Front Mic", 0x0 },
1532 { "Mix Mono", 0x3 },
1539 static struct snd_kcontrol_new ad1981_mixers
[] = {
1540 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1541 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1542 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1543 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1544 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1545 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1546 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1547 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1548 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1549 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1550 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1551 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1552 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
1553 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
1554 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1555 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1556 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1557 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1558 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1559 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT
),
1560 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1561 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1563 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1564 .name
= "Capture Source",
1565 .info
= ad198x_mux_enum_info
,
1566 .get
= ad198x_mux_enum_get
,
1567 .put
= ad198x_mux_enum_put
,
1569 /* identical with AD1983 */
1571 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1572 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1573 .info
= ad1983_spdif_route_info
,
1574 .get
= ad1983_spdif_route_get
,
1575 .put
= ad1983_spdif_route_put
,
1580 static struct hda_verb ad1981_init_verbs
[] = {
1581 /* Front, HP, Mono; mute as default */
1582 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1583 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1584 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1585 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1586 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1587 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1588 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1589 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1590 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1591 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1592 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1593 /* Front, HP selectors; from Mix */
1594 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1595 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1596 /* Mono selector; from Mix */
1597 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1598 /* Mic Mixer; select Front Mic */
1599 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1600 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1601 /* Mic boost: 0dB */
1602 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1603 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1604 /* Record selector: Front mic */
1605 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1606 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1607 /* SPDIF route: PCM */
1608 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1610 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1612 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1614 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1615 /* Front & Rear Mic Pins */
1616 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1617 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1619 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1621 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00},
1622 /* Line-Out as Input: disabled */
1623 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1627 #ifdef CONFIG_SND_HDA_POWER_SAVE
1628 static struct hda_amp_list ad1981_loopbacks
[] = {
1629 { 0x12, HDA_OUTPUT
, 0 }, /* Front Mic */
1630 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1631 { 0x1b, HDA_OUTPUT
, 0 }, /* Aux */
1632 { 0x1c, HDA_OUTPUT
, 0 }, /* Mic */
1633 { 0x1d, HDA_OUTPUT
, 0 }, /* CD */
1639 * Patch for HP nx6320
1641 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1642 * speaker output enabled _and_ mute-LED off.
1645 #define AD1981_HP_EVENT 0x37
1646 #define AD1981_MIC_EVENT 0x38
1648 static struct hda_verb ad1981_hp_init_verbs
[] = {
1649 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 }, /* default off */
1650 /* pin sensing on HP and Mic jacks */
1651 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1652 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1656 /* turn on/off EAPD (+ mute HP) as a master switch */
1657 static int ad1981_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
1658 struct snd_ctl_elem_value
*ucontrol
)
1660 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1661 struct ad198x_spec
*spec
= codec
->spec
;
1663 if (! ad198x_eapd_put(kcontrol
, ucontrol
))
1665 /* change speaker pin appropriately */
1666 snd_hda_codec_write(codec
, 0x05, 0,
1667 AC_VERB_SET_PIN_WIDGET_CONTROL
,
1668 spec
->cur_eapd
? PIN_OUT
: 0);
1669 /* toggle HP mute appropriately */
1670 snd_hda_codec_amp_stereo(codec
, 0x06, HDA_OUTPUT
, 0,
1672 spec
->cur_eapd
? 0 : HDA_AMP_MUTE
);
1676 /* bind volumes of both NID 0x05 and 0x06 */
1677 static struct hda_bind_ctls ad1981_hp_bind_master_vol
= {
1678 .ops
= &snd_hda_bind_vol
,
1680 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT
),
1681 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT
),
1686 /* mute internal speaker if HP is plugged */
1687 static void ad1981_hp_automute(struct hda_codec
*codec
)
1689 unsigned int present
;
1691 present
= snd_hda_jack_detect(codec
, 0x06);
1692 snd_hda_codec_amp_stereo(codec
, 0x05, HDA_OUTPUT
, 0,
1693 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
1696 /* toggle input of built-in and mic jack appropriately */
1697 static void ad1981_hp_automic(struct hda_codec
*codec
)
1699 static struct hda_verb mic_jack_on
[] = {
1700 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1701 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1704 static struct hda_verb mic_jack_off
[] = {
1705 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1706 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1709 unsigned int present
;
1711 present
= snd_hda_jack_detect(codec
, 0x08);
1713 snd_hda_sequence_write(codec
, mic_jack_on
);
1715 snd_hda_sequence_write(codec
, mic_jack_off
);
1718 /* unsolicited event for HP jack sensing */
1719 static void ad1981_hp_unsol_event(struct hda_codec
*codec
,
1724 case AD1981_HP_EVENT
:
1725 ad1981_hp_automute(codec
);
1727 case AD1981_MIC_EVENT
:
1728 ad1981_hp_automic(codec
);
1733 static struct hda_input_mux ad1981_hp_capture_source
= {
1737 { "Docking-Station", 0x1 },
1742 static struct snd_kcontrol_new ad1981_hp_mixers
[] = {
1743 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol
),
1745 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1746 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x05,
1747 .name
= "Master Playback Switch",
1748 .info
= ad198x_eapd_info
,
1749 .get
= ad198x_eapd_get
,
1750 .put
= ad1981_hp_master_sw_put
,
1751 .private_value
= 0x05,
1753 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1754 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1756 /* FIXME: analog mic/line loopback doesn't work with my tests...
1757 * (although recording is OK)
1759 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1760 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1761 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1762 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1763 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1764 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1765 /* FIXME: does this laptop have analog CD connection? */
1766 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1767 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1769 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1770 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT
),
1771 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1772 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1774 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1775 .name
= "Capture Source",
1776 .info
= ad198x_mux_enum_info
,
1777 .get
= ad198x_mux_enum_get
,
1778 .put
= ad198x_mux_enum_put
,
1783 /* initialize jack-sensing, too */
1784 static int ad1981_hp_init(struct hda_codec
*codec
)
1787 ad1981_hp_automute(codec
);
1788 ad1981_hp_automic(codec
);
1792 /* configuration for Toshiba Laptops */
1793 static struct hda_verb ad1981_toshiba_init_verbs
[] = {
1794 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x01 }, /* default on */
1795 /* pin sensing on HP and Mic jacks */
1796 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1797 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1801 static struct snd_kcontrol_new ad1981_toshiba_mixers
[] = {
1802 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT
),
1803 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT
),
1807 /* configuration for Lenovo Thinkpad T60 */
1808 static struct snd_kcontrol_new ad1981_thinkpad_mixers
[] = {
1809 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1810 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1811 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1812 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1813 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1814 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1815 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1816 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1817 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1818 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1819 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1821 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1822 .name
= "Capture Source",
1823 .info
= ad198x_mux_enum_info
,
1824 .get
= ad198x_mux_enum_get
,
1825 .put
= ad198x_mux_enum_put
,
1827 /* identical with AD1983 */
1829 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1830 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1831 .info
= ad1983_spdif_route_info
,
1832 .get
= ad1983_spdif_route_get
,
1833 .put
= ad1983_spdif_route_put
,
1838 static struct hda_input_mux ad1981_thinkpad_capture_source
= {
1856 static const char * const ad1981_models
[AD1981_MODELS
] = {
1858 [AD1981_THINKPAD
] = "thinkpad",
1859 [AD1981_BASIC
] = "basic",
1860 [AD1981_TOSHIBA
] = "toshiba"
1863 static struct snd_pci_quirk ad1981_cfg_tbl
[] = {
1864 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD
),
1865 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD
),
1867 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP
),
1868 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA
),
1869 /* Lenovo Thinkpad T60/X60/Z6xx */
1870 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD
),
1871 /* HP nx6320 (reversed SSID, H/W bug) */
1872 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP
),
1876 static int patch_ad1981(struct hda_codec
*codec
)
1878 struct ad198x_spec
*spec
;
1879 int err
, board_config
;
1881 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1887 err
= snd_hda_attach_beep_device(codec
, 0x10);
1892 set_beep_amp(spec
, 0x0d, 0, HDA_OUTPUT
);
1894 spec
->multiout
.max_channels
= 2;
1895 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1981_dac_nids
);
1896 spec
->multiout
.dac_nids
= ad1981_dac_nids
;
1897 spec
->multiout
.dig_out_nid
= AD1981_SPDIF_OUT
;
1898 spec
->num_adc_nids
= 1;
1899 spec
->adc_nids
= ad1981_adc_nids
;
1900 spec
->capsrc_nids
= ad1981_capsrc_nids
;
1901 spec
->input_mux
= &ad1981_capture_source
;
1902 spec
->num_mixers
= 1;
1903 spec
->mixers
[0] = ad1981_mixers
;
1904 spec
->num_init_verbs
= 1;
1905 spec
->init_verbs
[0] = ad1981_init_verbs
;
1906 spec
->spdif_route
= 0;
1907 #ifdef CONFIG_SND_HDA_POWER_SAVE
1908 spec
->loopback
.amplist
= ad1981_loopbacks
;
1910 spec
->vmaster_nid
= 0x05;
1912 codec
->patch_ops
= ad198x_patch_ops
;
1914 /* override some parameters */
1915 board_config
= snd_hda_check_board_config(codec
, AD1981_MODELS
,
1918 switch (board_config
) {
1920 spec
->mixers
[0] = ad1981_hp_mixers
;
1921 spec
->num_init_verbs
= 2;
1922 spec
->init_verbs
[1] = ad1981_hp_init_verbs
;
1923 spec
->multiout
.dig_out_nid
= 0;
1924 spec
->input_mux
= &ad1981_hp_capture_source
;
1926 codec
->patch_ops
.init
= ad1981_hp_init
;
1927 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
1928 /* set the upper-limit for mixer amp to 0dB for avoiding the
1929 * possible damage by overloading
1931 snd_hda_override_amp_caps(codec
, 0x11, HDA_INPUT
,
1932 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
1933 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
1934 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
1935 (1 << AC_AMPCAP_MUTE_SHIFT
));
1937 case AD1981_THINKPAD
:
1938 spec
->mixers
[0] = ad1981_thinkpad_mixers
;
1939 spec
->input_mux
= &ad1981_thinkpad_capture_source
;
1940 /* set the upper-limit for mixer amp to 0dB for avoiding the
1941 * possible damage by overloading
1943 snd_hda_override_amp_caps(codec
, 0x11, HDA_INPUT
,
1944 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
1945 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
1946 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
1947 (1 << AC_AMPCAP_MUTE_SHIFT
));
1949 case AD1981_TOSHIBA
:
1950 spec
->mixers
[0] = ad1981_hp_mixers
;
1951 spec
->mixers
[1] = ad1981_toshiba_mixers
;
1952 spec
->num_init_verbs
= 2;
1953 spec
->init_verbs
[1] = ad1981_toshiba_init_verbs
;
1954 spec
->multiout
.dig_out_nid
= 0;
1955 spec
->input_mux
= &ad1981_hp_capture_source
;
1956 codec
->patch_ops
.init
= ad1981_hp_init
;
1957 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
1961 codec
->no_trigger_sense
= 1;
1962 codec
->no_sticky_stream
= 1;
1971 * Output pins and routes
1973 * Pin Mix Sel DAC (*)
1974 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1975 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1976 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1977 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1978 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1979 * port-F 0x16 (mute) <- 0x2a <- 06
1980 * port-G 0x24 (mute) <- 0x27 <- 05
1981 * port-H 0x25 (mute) <- 0x28 <- 0a
1982 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1984 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1985 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1987 * Input pins and routes
1989 * pin boost mix input # / adc input #
1990 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1991 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1992 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1993 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1994 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1995 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1996 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1997 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2001 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2002 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2004 * Inputs of Analog Mix (0x20)
2005 * 0:Port-B (front mic)
2006 * 1:Port-C/G/H (line-in)
2008 * 3:Port-D (line-in/2)
2009 * 4:Port-E/G/H (mic-in)
2010 * 5:Port-F (mic2-in)
2016 * 1:Port-B (front mic-in)
2017 * 2:Port-C (line-in)
2018 * 3:Port-F (mic2-in)
2023 * 8:Port-D (line-in/2)
2026 * Proposed pin assignments by the datasheet
2029 * Port-A front headphone
2039 * Port-A front headphone
2041 * C rear line-in/surround
2043 * E rear mic-in/CLFE
2049 * D internal speaker (with EAPD)
2050 * E/F quad mic array
2058 AD1988_6STACK_DIG_FP
,
2067 /* reivision id to check workarounds */
2068 #define AD1988A_REV2 0x100200
2070 #define is_rev2(codec) \
2071 ((codec)->vendor_id == 0x11d41988 && \
2072 (codec)->revision_id == AD1988A_REV2)
2078 static hda_nid_t ad1988_6stack_dac_nids
[4] = {
2079 0x04, 0x06, 0x05, 0x0a
2082 static hda_nid_t ad1988_3stack_dac_nids
[3] = {
2086 /* for AD1988A revision-2, DAC2-4 are swapped */
2087 static hda_nid_t ad1988_6stack_dac_nids_rev2
[4] = {
2088 0x04, 0x05, 0x0a, 0x06
2091 static hda_nid_t ad1988_alt_dac_nid
[1] = {
2095 static hda_nid_t ad1988_3stack_dac_nids_rev2
[3] = {
2099 static hda_nid_t ad1988_adc_nids
[3] = {
2103 static hda_nid_t ad1988_capsrc_nids
[3] = {
2107 #define AD1988_SPDIF_OUT 0x02
2108 #define AD1988_SPDIF_OUT_HDMI 0x0b
2109 #define AD1988_SPDIF_IN 0x07
2111 static hda_nid_t ad1989b_slave_dig_outs
[] = {
2112 AD1988_SPDIF_OUT
, AD1988_SPDIF_OUT_HDMI
, 0
2115 static struct hda_input_mux ad1988_6stack_capture_source
= {
2118 { "Front Mic", 0x1 }, /* port-B */
2119 { "Line", 0x2 }, /* port-C */
2120 { "Mic", 0x4 }, /* port-E */
2126 static struct hda_input_mux ad1988_laptop_capture_source
= {
2129 { "Mic/Line", 0x1 }, /* port-B */
2137 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
2138 struct snd_ctl_elem_info
*uinfo
)
2140 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2141 struct ad198x_spec
*spec
= codec
->spec
;
2142 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
2143 spec
->num_channel_mode
);
2146 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
2147 struct snd_ctl_elem_value
*ucontrol
)
2149 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2150 struct ad198x_spec
*spec
= codec
->spec
;
2151 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
2152 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
2155 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
2156 struct snd_ctl_elem_value
*ucontrol
)
2158 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2159 struct ad198x_spec
*spec
= codec
->spec
;
2160 int err
= snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
2161 spec
->num_channel_mode
,
2162 &spec
->multiout
.max_channels
);
2163 if (err
>= 0 && spec
->need_dac_fix
)
2164 spec
->multiout
.num_dacs
= spec
->multiout
.max_channels
/ 2;
2169 static struct snd_kcontrol_new ad1988_6stack_mixers1
[] = {
2170 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2171 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2172 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2173 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2174 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2178 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2
[] = {
2179 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2180 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
2181 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2182 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT
),
2183 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2187 static struct snd_kcontrol_new ad1988_6stack_mixers2
[] = {
2188 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2189 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT
),
2190 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT
),
2191 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT
),
2192 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT
),
2193 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2194 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2196 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2197 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2198 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2199 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2200 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2201 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2202 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2203 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2205 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2206 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2208 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2209 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
2214 static struct snd_kcontrol_new ad1988_6stack_fp_mixers
[] = {
2215 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
2221 static struct snd_kcontrol_new ad1988_3stack_mixers1
[] = {
2222 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2223 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2224 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2225 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2229 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2
[] = {
2230 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2231 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2232 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT
),
2233 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT
),
2237 static struct snd_kcontrol_new ad1988_3stack_mixers2
[] = {
2238 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2239 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT
),
2240 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT
),
2241 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT
),
2242 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2243 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2245 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2246 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2247 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2248 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2249 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2250 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2251 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2252 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2254 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2255 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2257 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2258 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
2260 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2261 .name
= "Channel Mode",
2262 .info
= ad198x_ch_mode_info
,
2263 .get
= ad198x_ch_mode_get
,
2264 .put
= ad198x_ch_mode_put
,
2271 static struct snd_kcontrol_new ad1988_laptop_mixers
[] = {
2272 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2273 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT
),
2274 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2276 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2277 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2278 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2279 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2280 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2281 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2283 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2284 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2286 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2289 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2290 .name
= "External Amplifier",
2291 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x12,
2292 .info
= ad198x_eapd_info
,
2293 .get
= ad198x_eapd_get
,
2294 .put
= ad198x_eapd_put
,
2295 .private_value
= 0x12, /* port-D */
2302 static struct snd_kcontrol_new ad1988_capture_mixers
[] = {
2303 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
2304 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
2305 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
2306 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
2307 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT
),
2308 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT
),
2310 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2311 /* The multiple "Capture Source" controls confuse alsamixer
2312 * So call somewhat different..
2314 /* .name = "Capture Source", */
2315 .name
= "Input Source",
2317 .info
= ad198x_mux_enum_info
,
2318 .get
= ad198x_mux_enum_get
,
2319 .put
= ad198x_mux_enum_put
,
2324 static int ad1988_spdif_playback_source_info(struct snd_kcontrol
*kcontrol
,
2325 struct snd_ctl_elem_info
*uinfo
)
2327 static char *texts
[] = {
2328 "PCM", "ADC1", "ADC2", "ADC3"
2330 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
2332 uinfo
->value
.enumerated
.items
= 4;
2333 if (uinfo
->value
.enumerated
.item
>= 4)
2334 uinfo
->value
.enumerated
.item
= 3;
2335 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
2339 static int ad1988_spdif_playback_source_get(struct snd_kcontrol
*kcontrol
,
2340 struct snd_ctl_elem_value
*ucontrol
)
2342 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2345 sel
= snd_hda_codec_read(codec
, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE
,
2348 ucontrol
->value
.enumerated
.item
[0] = 0;
2350 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2351 AC_VERB_GET_CONNECT_SEL
, 0);
2356 ucontrol
->value
.enumerated
.item
[0] = sel
;
2361 static int ad1988_spdif_playback_source_put(struct snd_kcontrol
*kcontrol
,
2362 struct snd_ctl_elem_value
*ucontrol
)
2364 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2365 unsigned int val
, sel
;
2368 val
= ucontrol
->value
.enumerated
.item
[0];
2372 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2373 AC_VERB_GET_AMP_GAIN_MUTE
,
2375 change
= sel
& 0x80;
2377 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2378 AC_VERB_SET_AMP_GAIN_MUTE
,
2380 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2381 AC_VERB_SET_AMP_GAIN_MUTE
,
2385 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2386 AC_VERB_GET_AMP_GAIN_MUTE
,
2387 AC_AMP_GET_INPUT
| 0x01);
2388 change
= sel
& 0x80;
2390 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2391 AC_VERB_SET_AMP_GAIN_MUTE
,
2393 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2394 AC_VERB_SET_AMP_GAIN_MUTE
,
2397 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2398 AC_VERB_GET_CONNECT_SEL
, 0) + 1;
2399 change
|= sel
!= val
;
2401 snd_hda_codec_write_cache(codec
, 0x0b, 0,
2402 AC_VERB_SET_CONNECT_SEL
,
2408 static struct snd_kcontrol_new ad1988_spdif_out_mixers
[] = {
2409 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2411 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2412 .name
= "IEC958 Playback Source",
2413 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x1b,
2414 .info
= ad1988_spdif_playback_source_info
,
2415 .get
= ad1988_spdif_playback_source_get
,
2416 .put
= ad1988_spdif_playback_source_put
,
2421 static struct snd_kcontrol_new ad1988_spdif_in_mixers
[] = {
2422 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT
),
2426 static struct snd_kcontrol_new ad1989_spdif_out_mixers
[] = {
2427 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2428 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
2433 * initialization verbs
2437 * for 6-stack (+dig)
2439 static struct hda_verb ad1988_6stack_init_verbs
[] = {
2440 /* Front, Surround, CLFE, side DAC; unmute as default */
2441 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2442 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2443 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2444 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2445 /* Port-A front headphon path */
2446 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2447 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2448 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2449 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2450 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2451 /* Port-D line-out path */
2452 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2453 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2454 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2455 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2456 /* Port-F surround path */
2457 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2458 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2459 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2460 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2461 /* Port-G CLFE path */
2462 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2463 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2464 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2465 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2466 /* Port-H side path */
2467 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2468 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2469 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2470 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2472 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2473 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2474 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2475 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2476 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2477 /* Port-B front mic-in path */
2478 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2479 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2480 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2481 /* Port-C line-in path */
2482 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2483 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2484 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2485 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2486 /* Port-E mic-in path */
2487 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2488 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2489 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2490 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2491 /* Analog CD Input */
2492 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2493 /* Analog Mix output amp */
2494 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2499 static struct hda_verb ad1988_6stack_fp_init_verbs
[] = {
2500 /* Headphone; unmute as default */
2501 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2502 /* Port-A front headphon path */
2503 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* DAC0:03h */
2504 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2505 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2506 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2507 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2512 static struct hda_verb ad1988_capture_init_verbs
[] = {
2513 /* mute analog mix */
2514 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2515 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2516 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2517 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2518 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2519 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2520 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2521 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2522 /* select ADCs - front-mic */
2523 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2524 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2525 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2530 static struct hda_verb ad1988_spdif_init_verbs
[] = {
2532 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
2533 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* ADC1 */
2534 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2535 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2537 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2542 static struct hda_verb ad1988_spdif_in_init_verbs
[] = {
2543 /* unmute SPDIF input pin */
2544 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2548 /* AD1989 has no ADC -> SPDIF route */
2549 static struct hda_verb ad1989_spdif_init_verbs
[] = {
2550 /* SPDIF-1 out pin */
2551 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2552 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2553 /* SPDIF-2/HDMI out pin */
2554 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2555 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2560 * verbs for 3stack (+dig)
2562 static struct hda_verb ad1988_3stack_ch2_init
[] = {
2563 /* set port-C to line-in */
2564 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2565 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2566 /* set port-E to mic-in */
2567 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2568 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2572 static struct hda_verb ad1988_3stack_ch6_init
[] = {
2573 /* set port-C to surround out */
2574 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2575 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2576 /* set port-E to CLFE out */
2577 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2578 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2582 static struct hda_channel_mode ad1988_3stack_modes
[2] = {
2583 { 2, ad1988_3stack_ch2_init
},
2584 { 6, ad1988_3stack_ch6_init
},
2587 static struct hda_verb ad1988_3stack_init_verbs
[] = {
2588 /* Front, Surround, CLFE, side DAC; unmute as default */
2589 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2590 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2591 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2592 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2593 /* Port-A front headphon path */
2594 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2595 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2596 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2597 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2598 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2599 /* Port-D line-out path */
2600 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2601 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2602 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2603 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2605 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2606 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2607 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2608 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2609 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2610 /* Port-B front mic-in path */
2611 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2612 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2613 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2614 /* Port-C line-in/surround path - 6ch mode as default */
2615 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2616 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2617 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2618 {0x31, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* output sel: DAC 0x05 */
2619 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2620 /* Port-E mic-in/CLFE path - 6ch mode as default */
2621 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2622 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2623 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2624 {0x32, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* output sel: DAC 0x0a */
2625 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2626 /* mute analog mix */
2627 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2628 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2635 /* select ADCs - front-mic */
2636 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2637 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2638 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2639 /* Analog Mix output amp */
2640 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2645 * verbs for laptop mode (+dig)
2647 static struct hda_verb ad1988_laptop_hp_on
[] = {
2648 /* unmute port-A and mute port-D */
2649 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2650 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2653 static struct hda_verb ad1988_laptop_hp_off
[] = {
2654 /* mute port-A and unmute port-D */
2655 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2656 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2660 #define AD1988_HP_EVENT 0x01
2662 static struct hda_verb ad1988_laptop_init_verbs
[] = {
2663 /* Front, Surround, CLFE, side DAC; unmute as default */
2664 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2665 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2666 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2667 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2668 /* Port-A front headphon path */
2669 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2670 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2671 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2672 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2673 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2674 /* unsolicited event for pin-sense */
2675 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1988_HP_EVENT
},
2676 /* Port-D line-out path + EAPD */
2677 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2678 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2679 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2680 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2681 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x00}, /* EAPD-off */
2683 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2684 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2685 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2686 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2687 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2688 /* Port-B mic-in path */
2689 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2690 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2691 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2692 /* Port-C docking station - try to output */
2693 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2694 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2695 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2696 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2697 /* mute analog mix */
2698 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2699 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2700 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2701 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2702 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2703 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2704 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2705 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2706 /* select ADCs - mic */
2707 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2708 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2709 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2710 /* Analog Mix output amp */
2711 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2715 static void ad1988_laptop_unsol_event(struct hda_codec
*codec
, unsigned int res
)
2717 if ((res
>> 26) != AD1988_HP_EVENT
)
2719 if (snd_hda_jack_detect(codec
, 0x11))
2720 snd_hda_sequence_write(codec
, ad1988_laptop_hp_on
);
2722 snd_hda_sequence_write(codec
, ad1988_laptop_hp_off
);
2725 #ifdef CONFIG_SND_HDA_POWER_SAVE
2726 static struct hda_amp_list ad1988_loopbacks
[] = {
2727 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
2728 { 0x20, HDA_INPUT
, 1 }, /* Line */
2729 { 0x20, HDA_INPUT
, 4 }, /* Mic */
2730 { 0x20, HDA_INPUT
, 6 }, /* CD */
2736 * Automatic parse of I/O pins from the BIOS configuration
2744 static struct snd_kcontrol_new ad1988_control_templates
[] = {
2745 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
2746 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
2747 HDA_BIND_MUTE(NULL
, 0, 0, 0),
2750 /* add dynamic controls */
2751 static int add_control(struct ad198x_spec
*spec
, int type
, const char *name
,
2754 struct snd_kcontrol_new
*knew
;
2756 snd_array_init(&spec
->kctls
, sizeof(*knew
), 32);
2757 knew
= snd_array_new(&spec
->kctls
);
2760 *knew
= ad1988_control_templates
[type
];
2761 knew
->name
= kstrdup(name
, GFP_KERNEL
);
2764 if (get_amp_nid_(val
))
2765 knew
->subdevice
= HDA_SUBDEV_AMP_FLAG
;
2766 knew
->private_value
= val
;
2770 #define AD1988_PIN_CD_NID 0x18
2771 #define AD1988_PIN_BEEP_NID 0x10
2773 static hda_nid_t ad1988_mixer_nids
[8] = {
2774 /* A B C D E F G H */
2775 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2778 static inline hda_nid_t
ad1988_idx_to_dac(struct hda_codec
*codec
, int idx
)
2780 static hda_nid_t idx_to_dac
[8] = {
2781 /* A B C D E F G H */
2782 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2784 static hda_nid_t idx_to_dac_rev2
[8] = {
2785 /* A B C D E F G H */
2786 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2789 return idx_to_dac_rev2
[idx
];
2791 return idx_to_dac
[idx
];
2794 static hda_nid_t ad1988_boost_nids
[8] = {
2795 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2798 static int ad1988_pin_idx(hda_nid_t nid
)
2800 static hda_nid_t ad1988_io_pins
[8] = {
2801 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2804 for (i
= 0; i
< ARRAY_SIZE(ad1988_io_pins
); i
++)
2805 if (ad1988_io_pins
[i
] == nid
)
2807 return 0; /* should be -1 */
2810 static int ad1988_pin_to_loopback_idx(hda_nid_t nid
)
2812 static int loopback_idx
[8] = {
2813 2, 0, 1, 3, 4, 5, 1, 4
2816 case AD1988_PIN_CD_NID
:
2819 return loopback_idx
[ad1988_pin_idx(nid
)];
2823 static int ad1988_pin_to_adc_idx(hda_nid_t nid
)
2825 static int adc_idx
[8] = {
2826 0, 1, 2, 8, 4, 3, 6, 7
2829 case AD1988_PIN_CD_NID
:
2832 return adc_idx
[ad1988_pin_idx(nid
)];
2836 /* fill in the dac_nids table from the parsed pin configuration */
2837 static int ad1988_auto_fill_dac_nids(struct hda_codec
*codec
,
2838 const struct auto_pin_cfg
*cfg
)
2840 struct ad198x_spec
*spec
= codec
->spec
;
2843 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2845 /* check the pins hardwired to audio widget */
2846 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2847 idx
= ad1988_pin_idx(cfg
->line_out_pins
[i
]);
2848 spec
->multiout
.dac_nids
[i
] = ad1988_idx_to_dac(codec
, idx
);
2850 spec
->multiout
.num_dacs
= cfg
->line_outs
;
2854 /* add playback controls from the parsed DAC table */
2855 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec
*spec
,
2856 const struct auto_pin_cfg
*cfg
)
2859 static const char * const chname
[4] = {
2860 "Front", "Surround", NULL
/*CLFE*/, "Side"
2865 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2866 hda_nid_t dac
= spec
->multiout
.dac_nids
[i
];
2869 nid
= ad1988_mixer_nids
[ad1988_pin_idx(cfg
->line_out_pins
[i
])];
2872 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2873 "Center Playback Volume",
2874 HDA_COMPOSE_AMP_VAL(dac
, 1, 0, HDA_OUTPUT
));
2877 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2878 "LFE Playback Volume",
2879 HDA_COMPOSE_AMP_VAL(dac
, 2, 0, HDA_OUTPUT
));
2882 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
2883 "Center Playback Switch",
2884 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
));
2887 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
2888 "LFE Playback Switch",
2889 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
));
2893 sprintf(name
, "%s Playback Volume", chname
[i
]);
2894 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2895 HDA_COMPOSE_AMP_VAL(dac
, 3, 0, HDA_OUTPUT
));
2898 sprintf(name
, "%s Playback Switch", chname
[i
]);
2899 err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
2900 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
));
2908 /* add playback controls for speaker and HP outputs */
2909 static int ad1988_auto_create_extra_out(struct hda_codec
*codec
, hda_nid_t pin
,
2912 struct ad198x_spec
*spec
= codec
->spec
;
2920 idx
= ad1988_pin_idx(pin
);
2921 nid
= ad1988_idx_to_dac(codec
, idx
);
2922 /* check whether the corresponding DAC was already taken */
2923 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
2924 hda_nid_t pin
= spec
->autocfg
.line_out_pins
[i
];
2925 hda_nid_t dac
= ad1988_idx_to_dac(codec
, ad1988_pin_idx(pin
));
2929 if (i
>= spec
->autocfg
.line_outs
) {
2930 /* specify the DAC as the extra output */
2931 if (!spec
->multiout
.hp_nid
)
2932 spec
->multiout
.hp_nid
= nid
;
2934 spec
->multiout
.extra_out_nid
[0] = nid
;
2935 /* control HP volume/switch on the output mixer amp */
2936 sprintf(name
, "%s Playback Volume", pfx
);
2937 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2938 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
2942 nid
= ad1988_mixer_nids
[idx
];
2943 sprintf(name
, "%s Playback Switch", pfx
);
2944 if ((err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
2945 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2950 /* create input playback/capture controls for the given pin */
2951 static int new_analog_input(struct ad198x_spec
*spec
, hda_nid_t pin
,
2952 const char *ctlname
, int ctlidx
, int boost
)
2957 sprintf(name
, "%s Playback Volume", ctlname
);
2958 idx
= ad1988_pin_to_loopback_idx(pin
);
2959 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2960 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
2962 sprintf(name
, "%s Playback Switch", ctlname
);
2963 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
, name
,
2964 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
2968 idx
= ad1988_pin_idx(pin
);
2969 bnid
= ad1988_boost_nids
[idx
];
2971 sprintf(name
, "%s Boost Volume", ctlname
);
2972 return add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2973 HDA_COMPOSE_AMP_VAL(bnid
, 3, idx
, HDA_OUTPUT
));
2980 /* create playback/capture controls for input pins */
2981 static int ad1988_auto_create_analog_input_ctls(struct hda_codec
*codec
,
2982 const struct auto_pin_cfg
*cfg
)
2984 struct ad198x_spec
*spec
= codec
->spec
;
2985 struct hda_input_mux
*imux
= &spec
->private_imux
;
2986 int i
, err
, type
, type_idx
;
2988 for (i
= 0; i
< cfg
->num_inputs
; i
++) {
2990 type
= cfg
->inputs
[i
].type
;
2991 label
= hda_get_autocfg_input_label(codec
, cfg
, i
);
2992 snd_hda_add_imux_item(imux
, label
,
2993 ad1988_pin_to_adc_idx(cfg
->inputs
[i
].pin
),
2995 err
= new_analog_input(spec
, cfg
->inputs
[i
].pin
,
2997 type
== AUTO_PIN_MIC
);
3001 snd_hda_add_imux_item(imux
, "Mix", 9, NULL
);
3003 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
3004 "Analog Mix Playback Volume",
3005 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
3007 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
,
3008 "Analog Mix Playback Switch",
3009 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
3015 static void ad1988_auto_set_output_and_unmute(struct hda_codec
*codec
,
3016 hda_nid_t nid
, int pin_type
,
3020 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
3021 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
3023 case 0x11: /* port-A - DAC 04 */
3024 snd_hda_codec_write(codec
, 0x37, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
3026 case 0x14: /* port-B - DAC 06 */
3027 snd_hda_codec_write(codec
, 0x30, 0, AC_VERB_SET_CONNECT_SEL
, 0x02);
3029 case 0x15: /* port-C - DAC 05 */
3030 snd_hda_codec_write(codec
, 0x31, 0, AC_VERB_SET_CONNECT_SEL
, 0x00);
3032 case 0x17: /* port-E - DAC 0a */
3033 snd_hda_codec_write(codec
, 0x32, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
3035 case 0x13: /* mono - DAC 04 */
3036 snd_hda_codec_write(codec
, 0x36, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
3041 static void ad1988_auto_init_multi_out(struct hda_codec
*codec
)
3043 struct ad198x_spec
*spec
= codec
->spec
;
3046 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
3047 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
3048 ad1988_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
3052 static void ad1988_auto_init_extra_out(struct hda_codec
*codec
)
3054 struct ad198x_spec
*spec
= codec
->spec
;
3057 pin
= spec
->autocfg
.speaker_pins
[0];
3058 if (pin
) /* connect to front */
3059 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
3060 pin
= spec
->autocfg
.hp_pins
[0];
3061 if (pin
) /* connect to front */
3062 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
3065 static void ad1988_auto_init_analog_input(struct hda_codec
*codec
)
3067 struct ad198x_spec
*spec
= codec
->spec
;
3068 const struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
3071 for (i
= 0; i
< cfg
->num_inputs
; i
++) {
3072 hda_nid_t nid
= cfg
->inputs
[i
].pin
;
3074 case 0x15: /* port-C */
3075 snd_hda_codec_write(codec
, 0x33, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
3077 case 0x17: /* port-E */
3078 snd_hda_codec_write(codec
, 0x34, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
3081 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
3082 i
== AUTO_PIN_MIC
? PIN_VREF80
: PIN_IN
);
3083 if (nid
!= AD1988_PIN_CD_NID
)
3084 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3086 idx
= ad1988_pin_idx(nid
);
3087 if (ad1988_boost_nids
[idx
])
3088 snd_hda_codec_write(codec
, ad1988_boost_nids
[idx
], 0,
3089 AC_VERB_SET_AMP_GAIN_MUTE
,
3094 /* parse the BIOS configuration and set up the alc_spec */
3095 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3096 static int ad1988_parse_auto_config(struct hda_codec
*codec
)
3098 struct ad198x_spec
*spec
= codec
->spec
;
3101 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
3103 if ((err
= ad1988_auto_fill_dac_nids(codec
, &spec
->autocfg
)) < 0)
3105 if (! spec
->autocfg
.line_outs
)
3106 return 0; /* can't find valid BIOS pin config */
3107 if ((err
= ad1988_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
3108 (err
= ad1988_auto_create_extra_out(codec
,
3109 spec
->autocfg
.speaker_pins
[0],
3111 (err
= ad1988_auto_create_extra_out(codec
, spec
->autocfg
.hp_pins
[0],
3112 "Headphone")) < 0 ||
3113 (err
= ad1988_auto_create_analog_input_ctls(codec
, &spec
->autocfg
)) < 0)
3116 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
3118 if (spec
->autocfg
.dig_outs
)
3119 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3120 if (spec
->autocfg
.dig_in_pin
)
3121 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
3123 if (spec
->kctls
.list
)
3124 spec
->mixers
[spec
->num_mixers
++] = spec
->kctls
.list
;
3126 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_6stack_init_verbs
;
3128 spec
->input_mux
= &spec
->private_imux
;
3133 /* init callback for auto-configuration model -- overriding the default init */
3134 static int ad1988_auto_init(struct hda_codec
*codec
)
3137 ad1988_auto_init_multi_out(codec
);
3138 ad1988_auto_init_extra_out(codec
);
3139 ad1988_auto_init_analog_input(codec
);
3146 static const char * const ad1988_models
[AD1988_MODEL_LAST
] = {
3147 [AD1988_6STACK
] = "6stack",
3148 [AD1988_6STACK_DIG
] = "6stack-dig",
3149 [AD1988_6STACK_DIG_FP
] = "6stack-dig-fp",
3150 [AD1988_3STACK
] = "3stack",
3151 [AD1988_3STACK_DIG
] = "3stack-dig",
3152 [AD1988_LAPTOP
] = "laptop",
3153 [AD1988_LAPTOP_DIG
] = "laptop-dig",
3154 [AD1988_AUTO
] = "auto",
3157 static struct snd_pci_quirk ad1988_cfg_tbl
[] = {
3158 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG
),
3159 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG
),
3160 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG
),
3161 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG
),
3165 static int patch_ad1988(struct hda_codec
*codec
)
3167 struct ad198x_spec
*spec
;
3168 int err
, board_config
;
3170 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3177 snd_printk(KERN_INFO
"patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3179 board_config
= snd_hda_check_board_config(codec
, AD1988_MODEL_LAST
,
3180 ad1988_models
, ad1988_cfg_tbl
);
3181 if (board_config
< 0) {
3182 printk(KERN_INFO
"hda_codec: %s: BIOS auto-probing.\n",
3184 board_config
= AD1988_AUTO
;
3187 if (board_config
== AD1988_AUTO
) {
3188 /* automatic parse from the BIOS config */
3189 err
= ad1988_parse_auto_config(codec
);
3194 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3195 board_config
= AD1988_6STACK
;
3199 err
= snd_hda_attach_beep_device(codec
, 0x10);
3204 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3206 switch (board_config
) {
3208 case AD1988_6STACK_DIG
:
3209 case AD1988_6STACK_DIG_FP
:
3210 spec
->multiout
.max_channels
= 8;
3211 spec
->multiout
.num_dacs
= 4;
3213 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids_rev2
;
3215 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids
;
3216 spec
->input_mux
= &ad1988_6stack_capture_source
;
3217 spec
->num_mixers
= 2;
3219 spec
->mixers
[0] = ad1988_6stack_mixers1_rev2
;
3221 spec
->mixers
[0] = ad1988_6stack_mixers1
;
3222 spec
->mixers
[1] = ad1988_6stack_mixers2
;
3223 spec
->num_init_verbs
= 1;
3224 spec
->init_verbs
[0] = ad1988_6stack_init_verbs
;
3225 if (board_config
== AD1988_6STACK_DIG_FP
) {
3227 spec
->mixers
[2] = ad1988_6stack_fp_mixers
;
3228 spec
->num_init_verbs
++;
3229 spec
->init_verbs
[1] = ad1988_6stack_fp_init_verbs
;
3230 spec
->slave_vols
= ad1988_6stack_fp_slave_vols
;
3231 spec
->slave_sws
= ad1988_6stack_fp_slave_sws
;
3232 spec
->alt_dac_nid
= ad1988_alt_dac_nid
;
3233 spec
->stream_analog_alt_playback
=
3234 &ad198x_pcm_analog_alt_playback
;
3236 if ((board_config
== AD1988_6STACK_DIG
) ||
3237 (board_config
== AD1988_6STACK_DIG_FP
)) {
3238 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3239 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
3243 case AD1988_3STACK_DIG
:
3244 spec
->multiout
.max_channels
= 6;
3245 spec
->multiout
.num_dacs
= 3;
3247 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids_rev2
;
3249 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3250 spec
->input_mux
= &ad1988_6stack_capture_source
;
3251 spec
->channel_mode
= ad1988_3stack_modes
;
3252 spec
->num_channel_mode
= ARRAY_SIZE(ad1988_3stack_modes
);
3253 spec
->num_mixers
= 2;
3255 spec
->mixers
[0] = ad1988_3stack_mixers1_rev2
;
3257 spec
->mixers
[0] = ad1988_3stack_mixers1
;
3258 spec
->mixers
[1] = ad1988_3stack_mixers2
;
3259 spec
->num_init_verbs
= 1;
3260 spec
->init_verbs
[0] = ad1988_3stack_init_verbs
;
3261 if (board_config
== AD1988_3STACK_DIG
)
3262 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3265 case AD1988_LAPTOP_DIG
:
3266 spec
->multiout
.max_channels
= 2;
3267 spec
->multiout
.num_dacs
= 1;
3268 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3269 spec
->input_mux
= &ad1988_laptop_capture_source
;
3270 spec
->num_mixers
= 1;
3271 spec
->mixers
[0] = ad1988_laptop_mixers
;
3272 spec
->inv_eapd
= 1; /* inverted EAPD */
3273 spec
->num_init_verbs
= 1;
3274 spec
->init_verbs
[0] = ad1988_laptop_init_verbs
;
3275 if (board_config
== AD1988_LAPTOP_DIG
)
3276 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3280 spec
->num_adc_nids
= ARRAY_SIZE(ad1988_adc_nids
);
3281 spec
->adc_nids
= ad1988_adc_nids
;
3282 spec
->capsrc_nids
= ad1988_capsrc_nids
;
3283 spec
->mixers
[spec
->num_mixers
++] = ad1988_capture_mixers
;
3284 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_capture_init_verbs
;
3285 if (spec
->multiout
.dig_out_nid
) {
3286 if (codec
->vendor_id
>= 0x11d4989a) {
3287 spec
->mixers
[spec
->num_mixers
++] =
3288 ad1989_spdif_out_mixers
;
3289 spec
->init_verbs
[spec
->num_init_verbs
++] =
3290 ad1989_spdif_init_verbs
;
3291 codec
->slave_dig_outs
= ad1989b_slave_dig_outs
;
3293 spec
->mixers
[spec
->num_mixers
++] =
3294 ad1988_spdif_out_mixers
;
3295 spec
->init_verbs
[spec
->num_init_verbs
++] =
3296 ad1988_spdif_init_verbs
;
3299 if (spec
->dig_in_nid
&& codec
->vendor_id
< 0x11d4989a) {
3300 spec
->mixers
[spec
->num_mixers
++] = ad1988_spdif_in_mixers
;
3301 spec
->init_verbs
[spec
->num_init_verbs
++] =
3302 ad1988_spdif_in_init_verbs
;
3305 codec
->patch_ops
= ad198x_patch_ops
;
3306 switch (board_config
) {
3308 codec
->patch_ops
.init
= ad1988_auto_init
;
3311 case AD1988_LAPTOP_DIG
:
3312 codec
->patch_ops
.unsol_event
= ad1988_laptop_unsol_event
;
3315 #ifdef CONFIG_SND_HDA_POWER_SAVE
3316 spec
->loopback
.amplist
= ad1988_loopbacks
;
3318 spec
->vmaster_nid
= 0x04;
3320 codec
->no_trigger_sense
= 1;
3321 codec
->no_sticky_stream
= 1;
3330 * port-B - front line/mic-in
3331 * port-E - aux in/out
3332 * port-F - aux in/out
3333 * port-C - rear line/mic-in
3334 * port-D - rear line/hp-out
3335 * port-A - front line/hp-out
3337 * AD1984 = AD1884 + two digital mic-ins
3340 * For simplicity, we share the single DAC for both HP and line-outs
3341 * right now. The inidividual playbacks could be easily implemented,
3342 * but no build-up framework is given, so far.
3345 static hda_nid_t ad1884_dac_nids
[1] = {
3349 static hda_nid_t ad1884_adc_nids
[2] = {
3353 static hda_nid_t ad1884_capsrc_nids
[2] = {
3357 #define AD1884_SPDIF_OUT 0x02
3359 static struct hda_input_mux ad1884_capture_source
= {
3362 { "Front Mic", 0x0 },
3369 static struct snd_kcontrol_new ad1884_base_mixers
[] = {
3370 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3371 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3372 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3373 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3374 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3375 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3376 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3377 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3378 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3379 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3380 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3381 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3382 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
3383 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3384 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3385 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3386 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3387 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3389 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3390 /* The multiple "Capture Source" controls confuse alsamixer
3391 * So call somewhat different..
3393 /* .name = "Capture Source", */
3394 .name
= "Input Source",
3396 .info
= ad198x_mux_enum_info
,
3397 .get
= ad198x_mux_enum_get
,
3398 .put
= ad198x_mux_enum_put
,
3400 /* SPDIF controls */
3401 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3403 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3404 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3405 /* identical with ad1983 */
3406 .info
= ad1983_spdif_route_info
,
3407 .get
= ad1983_spdif_route_get
,
3408 .put
= ad1983_spdif_route_put
,
3413 static struct snd_kcontrol_new ad1984_dmic_mixers
[] = {
3414 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT
),
3415 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT
),
3416 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3418 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3424 * initialization verbs
3426 static struct hda_verb ad1884_init_verbs
[] = {
3427 /* DACs; mute as default */
3428 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3429 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3430 /* Port-A (HP) mixer */
3431 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3432 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3434 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3435 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3436 /* HP selector - select DAC2 */
3437 {0x22, AC_VERB_SET_CONNECT_SEL
, 0x1},
3438 /* Port-D (Line-out) mixer */
3439 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3440 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3442 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3443 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3444 /* Mono-out mixer */
3445 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3446 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3448 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3449 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3451 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
3452 /* Port-B (front mic) pin */
3453 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3454 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3455 /* Port-C (rear mic) pin */
3456 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3457 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3458 /* Analog mixer; mute as default */
3459 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3460 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3461 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3462 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3463 /* Analog Mix output amp */
3464 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
3465 /* SPDIF output selector */
3466 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
3467 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
3471 #ifdef CONFIG_SND_HDA_POWER_SAVE
3472 static struct hda_amp_list ad1884_loopbacks
[] = {
3473 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
3474 { 0x20, HDA_INPUT
, 1 }, /* Mic */
3475 { 0x20, HDA_INPUT
, 2 }, /* CD */
3476 { 0x20, HDA_INPUT
, 4 }, /* Docking */
3481 static const char * const ad1884_slave_vols
[] = {
3482 "PCM Playback Volume",
3483 "Mic Playback Volume",
3484 "Mono Playback Volume",
3485 "Front Mic Playback Volume",
3486 "Mic Playback Volume",
3487 "CD Playback Volume",
3488 "Internal Mic Playback Volume",
3489 "Docking Mic Playback Volume",
3490 /* "Beep Playback Volume", */
3491 "IEC958 Playback Volume",
3495 static int patch_ad1884(struct hda_codec
*codec
)
3497 struct ad198x_spec
*spec
;
3500 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3506 err
= snd_hda_attach_beep_device(codec
, 0x10);
3511 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3513 spec
->multiout
.max_channels
= 2;
3514 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884_dac_nids
);
3515 spec
->multiout
.dac_nids
= ad1884_dac_nids
;
3516 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3517 spec
->num_adc_nids
= ARRAY_SIZE(ad1884_adc_nids
);
3518 spec
->adc_nids
= ad1884_adc_nids
;
3519 spec
->capsrc_nids
= ad1884_capsrc_nids
;
3520 spec
->input_mux
= &ad1884_capture_source
;
3521 spec
->num_mixers
= 1;
3522 spec
->mixers
[0] = ad1884_base_mixers
;
3523 spec
->num_init_verbs
= 1;
3524 spec
->init_verbs
[0] = ad1884_init_verbs
;
3525 spec
->spdif_route
= 0;
3526 #ifdef CONFIG_SND_HDA_POWER_SAVE
3527 spec
->loopback
.amplist
= ad1884_loopbacks
;
3529 spec
->vmaster_nid
= 0x04;
3530 /* we need to cover all playback volumes */
3531 spec
->slave_vols
= ad1884_slave_vols
;
3533 codec
->patch_ops
= ad198x_patch_ops
;
3535 codec
->no_trigger_sense
= 1;
3536 codec
->no_sticky_stream
= 1;
3542 * Lenovo Thinkpad T61/X61
3544 static struct hda_input_mux ad1984_thinkpad_capture_source
= {
3548 { "Internal Mic", 0x1 },
3550 { "Docking-Station", 0x4 },
3556 * Dell Precision T3400
3558 static struct hda_input_mux ad1984_dell_desktop_capture_source
= {
3561 { "Front Mic", 0x0 },
3568 static struct snd_kcontrol_new ad1984_thinkpad_mixers
[] = {
3569 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3570 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3571 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3572 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3573 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3574 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3575 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3576 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3577 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT
),
3578 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT
),
3579 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3580 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3581 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3582 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
3583 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
3584 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3585 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3586 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3587 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3589 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3590 /* The multiple "Capture Source" controls confuse alsamixer
3591 * So call somewhat different..
3593 /* .name = "Capture Source", */
3594 .name
= "Input Source",
3596 .info
= ad198x_mux_enum_info
,
3597 .get
= ad198x_mux_enum_get
,
3598 .put
= ad198x_mux_enum_put
,
3600 /* SPDIF controls */
3601 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3603 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3604 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3605 /* identical with ad1983 */
3606 .info
= ad1983_spdif_route_info
,
3607 .get
= ad1983_spdif_route_get
,
3608 .put
= ad1983_spdif_route_put
,
3613 /* additional verbs */
3614 static struct hda_verb ad1984_thinkpad_init_verbs
[] = {
3615 /* Port-E (docking station mic) pin */
3616 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3617 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3618 /* docking mic boost */
3619 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3620 /* Analog PC Beeper - allow firmware/ACPI beeps */
3621 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3) | 0x1a},
3622 /* Analog mixer - docking mic; mute as default */
3623 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3624 /* enable EAPD bit */
3625 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
3630 * Dell Precision T3400
3632 static struct snd_kcontrol_new ad1984_dell_desktop_mixers
[] = {
3633 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3634 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3635 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3636 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3637 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3638 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3639 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3640 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT
),
3641 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT
),
3642 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT
),
3643 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3644 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3645 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3646 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3647 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3649 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3650 /* The multiple "Capture Source" controls confuse alsamixer
3651 * So call somewhat different..
3653 /* .name = "Capture Source", */
3654 .name
= "Input Source",
3656 .info
= ad198x_mux_enum_info
,
3657 .get
= ad198x_mux_enum_get
,
3658 .put
= ad198x_mux_enum_put
,
3663 /* Digial MIC ADC NID 0x05 + 0x06 */
3664 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream
*hinfo
,
3665 struct hda_codec
*codec
,
3666 unsigned int stream_tag
,
3667 unsigned int format
,
3668 struct snd_pcm_substream
*substream
)
3670 snd_hda_codec_setup_stream(codec
, 0x05 + substream
->number
,
3671 stream_tag
, 0, format
);
3675 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream
*hinfo
,
3676 struct hda_codec
*codec
,
3677 struct snd_pcm_substream
*substream
)
3679 snd_hda_codec_cleanup_stream(codec
, 0x05 + substream
->number
);
3683 static struct hda_pcm_stream ad1984_pcm_dmic_capture
= {
3689 .prepare
= ad1984_pcm_dmic_prepare
,
3690 .cleanup
= ad1984_pcm_dmic_cleanup
3694 static int ad1984_build_pcms(struct hda_codec
*codec
)
3696 struct ad198x_spec
*spec
= codec
->spec
;
3697 struct hda_pcm
*info
;
3700 err
= ad198x_build_pcms(codec
);
3704 info
= spec
->pcm_rec
+ codec
->num_pcms
;
3706 info
->name
= "AD1984 Digital Mic";
3707 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad1984_pcm_dmic_capture
;
3715 AD1984_DELL_DESKTOP
,
3719 static const char * const ad1984_models
[AD1984_MODELS
] = {
3720 [AD1984_BASIC
] = "basic",
3721 [AD1984_THINKPAD
] = "thinkpad",
3722 [AD1984_DELL_DESKTOP
] = "dell_desktop",
3725 static struct snd_pci_quirk ad1984_cfg_tbl
[] = {
3726 /* Lenovo Thinkpad T61/X61 */
3727 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD
),
3728 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP
),
3729 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP
),
3733 static int patch_ad1984(struct hda_codec
*codec
)
3735 struct ad198x_spec
*spec
;
3736 int board_config
, err
;
3738 err
= patch_ad1884(codec
);
3742 board_config
= snd_hda_check_board_config(codec
, AD1984_MODELS
,
3743 ad1984_models
, ad1984_cfg_tbl
);
3744 switch (board_config
) {
3746 /* additional digital mics */
3747 spec
->mixers
[spec
->num_mixers
++] = ad1984_dmic_mixers
;
3748 codec
->patch_ops
.build_pcms
= ad1984_build_pcms
;
3750 case AD1984_THINKPAD
:
3751 if (codec
->subsystem_id
== 0x17aa20fb) {
3752 /* Thinpad X300 does not have the ability to do SPDIF,
3753 or attach to docking station to use SPDIF */
3754 spec
->multiout
.dig_out_nid
= 0;
3756 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3757 spec
->input_mux
= &ad1984_thinkpad_capture_source
;
3758 spec
->mixers
[0] = ad1984_thinkpad_mixers
;
3759 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1984_thinkpad_init_verbs
;
3760 spec
->analog_beep
= 1;
3762 case AD1984_DELL_DESKTOP
:
3763 spec
->multiout
.dig_out_nid
= 0;
3764 spec
->input_mux
= &ad1984_dell_desktop_capture_source
;
3765 spec
->mixers
[0] = ad1984_dell_desktop_mixers
;
3773 * AD1883 / AD1884A / AD1984A / AD1984B
3775 * port-B (0x14) - front mic-in
3776 * port-E (0x1c) - rear mic-in
3777 * port-F (0x16) - CD / ext out
3778 * port-C (0x15) - rear line-in
3779 * port-D (0x12) - rear line-out
3780 * port-A (0x11) - front hp-out
3782 * AD1984A = AD1884A + digital-mic
3783 * AD1883 = equivalent with AD1984A
3784 * AD1984B = AD1984A + extra SPDIF-out
3787 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3790 static hda_nid_t ad1884a_dac_nids
[1] = {
3794 #define ad1884a_adc_nids ad1884_adc_nids
3795 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3797 #define AD1884A_SPDIF_OUT 0x02
3799 static struct hda_input_mux ad1884a_capture_source
= {
3802 { "Front Mic", 0x0 },
3810 static struct snd_kcontrol_new ad1884a_base_mixers
[] = {
3811 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3812 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
3813 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3814 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3815 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3816 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3817 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3818 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3819 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3820 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3821 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
3822 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
3823 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3824 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3825 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3826 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3827 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3828 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT
),
3829 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
3830 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3831 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3832 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3833 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3835 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3836 /* The multiple "Capture Source" controls confuse alsamixer
3837 * So call somewhat different..
3839 /* .name = "Capture Source", */
3840 .name
= "Input Source",
3842 .info
= ad198x_mux_enum_info
,
3843 .get
= ad198x_mux_enum_get
,
3844 .put
= ad198x_mux_enum_put
,
3846 /* SPDIF controls */
3847 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3849 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3850 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3851 /* identical with ad1983 */
3852 .info
= ad1983_spdif_route_info
,
3853 .get
= ad1983_spdif_route_get
,
3854 .put
= ad1983_spdif_route_put
,
3860 * initialization verbs
3862 static struct hda_verb ad1884a_init_verbs
[] = {
3863 /* DACs; unmute as default */
3864 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3865 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3866 /* Port-A (HP) mixer - route only from analog mixer */
3867 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3868 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3870 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3871 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3872 /* Port-D (Line-out) mixer - route only from analog mixer */
3873 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3874 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3876 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3877 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3878 /* Mono-out mixer - route only from analog mixer */
3879 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3880 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3882 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3883 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3884 /* Port-B (front mic) pin */
3885 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3886 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3887 /* Port-C (rear line-in) pin */
3888 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3889 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3890 /* Port-E (rear mic) pin */
3891 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3892 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3893 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* no boost */
3894 /* Port-F (CD) pin */
3895 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3896 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3897 /* Analog mixer; mute as default */
3898 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3899 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3900 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3901 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3902 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)}, /* aux */
3903 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
3904 /* Analog Mix output amp */
3905 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3906 /* capture sources */
3907 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
3908 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3909 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
3910 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3911 /* SPDIF output amp */
3912 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
3916 #ifdef CONFIG_SND_HDA_POWER_SAVE
3917 static struct hda_amp_list ad1884a_loopbacks
[] = {
3918 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
3919 { 0x20, HDA_INPUT
, 1 }, /* Mic */
3920 { 0x20, HDA_INPUT
, 2 }, /* CD */
3921 { 0x20, HDA_INPUT
, 4 }, /* Docking */
3929 * Port A: Headphone jack
3931 * Port C: Internal MIC
3932 * Port D: Dock Line Out (if enabled)
3933 * Port E: Dock Line In (if enabled)
3934 * Port F: Internal speakers
3937 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol
*kcontrol
,
3938 struct snd_ctl_elem_value
*ucontrol
)
3940 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
3941 int ret
= snd_hda_mixer_amp_switch_put(kcontrol
, ucontrol
);
3942 int mute
= (!ucontrol
->value
.integer
.value
[0] &&
3943 !ucontrol
->value
.integer
.value
[1]);
3944 /* toggle GPIO1 according to the mute state */
3945 snd_hda_codec_write_cache(codec
, 0x01, 0, AC_VERB_SET_GPIO_DATA
,
3950 static struct snd_kcontrol_new ad1884a_laptop_mixers
[] = {
3951 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3953 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3954 .name
= "Master Playback Switch",
3955 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
3956 .info
= snd_hda_mixer_amp_switch_info
,
3957 .get
= snd_hda_mixer_amp_switch_get
,
3958 .put
= ad1884a_mobile_master_sw_put
,
3959 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
3961 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3962 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3963 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3964 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3965 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3966 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3967 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3968 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3969 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3970 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3971 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
3972 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
3973 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3974 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3978 static struct snd_kcontrol_new ad1884a_mobile_mixers
[] = {
3979 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3980 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3982 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3983 .name
= "Master Playback Switch",
3984 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
3985 .info
= snd_hda_mixer_amp_switch_info
,
3986 .get
= snd_hda_mixer_amp_switch_get
,
3987 .put
= ad1884a_mobile_master_sw_put
,
3988 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
3990 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3991 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3992 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT
),
3993 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT
),
3994 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3995 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3999 /* mute internal speaker if HP is plugged */
4000 static void ad1884a_hp_automute(struct hda_codec
*codec
)
4002 unsigned int present
;
4004 present
= snd_hda_jack_detect(codec
, 0x11);
4005 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
4006 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4007 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
4008 present
? 0x00 : 0x02);
4011 /* switch to external mic if plugged */
4012 static void ad1884a_hp_automic(struct hda_codec
*codec
)
4014 unsigned int present
;
4016 present
= snd_hda_jack_detect(codec
, 0x14);
4017 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
,
4021 #define AD1884A_HP_EVENT 0x37
4022 #define AD1884A_MIC_EVENT 0x36
4024 /* unsolicited event for HP jack sensing */
4025 static void ad1884a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
4027 switch (res
>> 26) {
4028 case AD1884A_HP_EVENT
:
4029 ad1884a_hp_automute(codec
);
4031 case AD1884A_MIC_EVENT
:
4032 ad1884a_hp_automic(codec
);
4037 /* initialize jack-sensing, too */
4038 static int ad1884a_hp_init(struct hda_codec
*codec
)
4041 ad1884a_hp_automute(codec
);
4042 ad1884a_hp_automic(codec
);
4046 /* mute internal speaker if HP or docking HP is plugged */
4047 static void ad1884a_laptop_automute(struct hda_codec
*codec
)
4049 unsigned int present
;
4051 present
= snd_hda_jack_detect(codec
, 0x11);
4053 present
= snd_hda_jack_detect(codec
, 0x12);
4054 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
4055 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4056 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
4057 present
? 0x00 : 0x02);
4060 /* switch to external mic if plugged */
4061 static void ad1884a_laptop_automic(struct hda_codec
*codec
)
4065 if (snd_hda_jack_detect(codec
, 0x14))
4067 else if (snd_hda_jack_detect(codec
, 0x1c))
4071 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
, idx
);
4074 /* unsolicited event for HP jack sensing */
4075 static void ad1884a_laptop_unsol_event(struct hda_codec
*codec
,
4078 switch (res
>> 26) {
4079 case AD1884A_HP_EVENT
:
4080 ad1884a_laptop_automute(codec
);
4082 case AD1884A_MIC_EVENT
:
4083 ad1884a_laptop_automic(codec
);
4088 /* initialize jack-sensing, too */
4089 static int ad1884a_laptop_init(struct hda_codec
*codec
)
4092 ad1884a_laptop_automute(codec
);
4093 ad1884a_laptop_automic(codec
);
4097 /* additional verbs for laptop model */
4098 static struct hda_verb ad1884a_laptop_verbs
[] = {
4099 /* Port-A (HP) pin - always unmuted */
4100 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4101 /* Port-F (int speaker) mixer - route only from analog mixer */
4102 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4103 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4104 /* Port-F (int speaker) pin */
4105 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4106 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4107 /* required for compaq 6530s/6531s speaker output */
4108 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4109 /* Port-C pin - internal mic-in */
4110 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4111 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4112 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4113 /* Port-D (docking line-out) pin - default unmuted */
4114 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4116 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4117 /* unsolicited event for pin-sense */
4118 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4119 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4120 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4121 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4122 /* allow to touch GPIO1 (for mute control) */
4123 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4124 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4125 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4129 static struct hda_verb ad1884a_mobile_verbs
[] = {
4130 /* DACs; unmute as default */
4131 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4132 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4133 /* Port-A (HP) mixer - route only from analog mixer */
4134 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4135 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4137 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4138 /* Port-A (HP) pin - always unmuted */
4139 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4140 /* Port-B (mic jack) pin */
4141 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4142 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4143 /* Port-C (int mic) pin */
4144 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4145 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4146 /* Port-F (int speaker) mixer - route only from analog mixer */
4147 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4148 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4150 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4151 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4152 /* Analog mixer; mute as default */
4153 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4154 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4155 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4156 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4157 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4158 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4159 /* Analog Mix output amp */
4160 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4161 /* capture sources */
4162 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4163 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4164 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4165 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4166 /* unsolicited event for pin-sense */
4167 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4168 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4169 /* allow to touch GPIO1 (for mute control) */
4170 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4171 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4172 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4181 * 0x17 - built-in mic
4184 static struct hda_verb ad1984a_thinkpad_verbs
[] = {
4186 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4188 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4190 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
4191 /* unsolicited event for pin-sense */
4192 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4193 /* internal mic - dmic */
4194 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4195 /* set magic COEFs for dmic */
4196 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
4197 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
4201 static struct snd_kcontrol_new ad1984a_thinkpad_mixers
[] = {
4202 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4203 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
4204 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4205 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4206 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4207 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4208 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
4209 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT
),
4210 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4211 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4213 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4214 .name
= "Capture Source",
4215 .info
= ad198x_mux_enum_info
,
4216 .get
= ad198x_mux_enum_get
,
4217 .put
= ad198x_mux_enum_put
,
4222 static struct hda_input_mux ad1984a_thinkpad_capture_source
= {
4226 { "Internal Mic", 0x5 },
4231 /* mute internal speaker if HP is plugged */
4232 static void ad1984a_thinkpad_automute(struct hda_codec
*codec
)
4234 unsigned int present
;
4236 present
= snd_hda_jack_detect(codec
, 0x11);
4237 snd_hda_codec_amp_stereo(codec
, 0x12, HDA_OUTPUT
, 0,
4238 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4241 /* unsolicited event for HP jack sensing */
4242 static void ad1984a_thinkpad_unsol_event(struct hda_codec
*codec
,
4245 if ((res
>> 26) != AD1884A_HP_EVENT
)
4247 ad1984a_thinkpad_automute(codec
);
4250 /* initialize jack-sensing, too */
4251 static int ad1984a_thinkpad_init(struct hda_codec
*codec
)
4254 ad1984a_thinkpad_automute(codec
);
4260 * port-A (0x11) - front hp-out
4261 * port-B (0x14) - unused
4262 * port-C (0x15) - unused
4263 * port-D (0x12) - rear line out
4264 * port-E (0x1c) - front mic-in
4265 * port-F (0x16) - Internal speakers
4266 * digital-mic (0x17) - Internal mic
4269 static struct hda_verb ad1984a_touchsmart_verbs
[] = {
4270 /* DACs; unmute as default */
4271 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4272 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4273 /* Port-A (HP) mixer - route only from analog mixer */
4274 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4275 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4277 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4278 /* Port-A (HP) pin - always unmuted */
4279 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4280 /* Port-E (int speaker) mixer - route only from analog mixer */
4281 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, 0x03},
4283 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4284 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4285 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4286 /* Port-F (int speaker) mixer - route only from analog mixer */
4287 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4288 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4290 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4291 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4292 /* Analog mixer; mute as default */
4293 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4294 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4295 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4296 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4297 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4298 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4299 /* Analog Mix output amp */
4300 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4301 /* capture sources */
4302 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4303 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4304 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4305 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4306 /* unsolicited event for pin-sense */
4307 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4308 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4309 /* allow to touch GPIO1 (for mute control) */
4310 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4311 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4312 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4313 /* internal mic - dmic */
4314 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4315 /* set magic COEFs for dmic */
4316 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
4317 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
4321 static struct snd_kcontrol_new ad1984a_touchsmart_mixers
[] = {
4322 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4323 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4325 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4326 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
4327 .name
= "Master Playback Switch",
4328 .info
= snd_hda_mixer_amp_switch_info
,
4329 .get
= snd_hda_mixer_amp_switch_get
,
4330 .put
= ad1884a_mobile_master_sw_put
,
4331 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
4333 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4334 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4335 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4336 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4337 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
4338 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT
),
4342 /* switch to external mic if plugged */
4343 static void ad1984a_touchsmart_automic(struct hda_codec
*codec
)
4345 if (snd_hda_jack_detect(codec
, 0x1c))
4346 snd_hda_codec_write(codec
, 0x0c, 0,
4347 AC_VERB_SET_CONNECT_SEL
, 0x4);
4349 snd_hda_codec_write(codec
, 0x0c, 0,
4350 AC_VERB_SET_CONNECT_SEL
, 0x5);
4354 /* unsolicited event for HP jack sensing */
4355 static void ad1984a_touchsmart_unsol_event(struct hda_codec
*codec
,
4358 switch (res
>> 26) {
4359 case AD1884A_HP_EVENT
:
4360 ad1884a_hp_automute(codec
);
4362 case AD1884A_MIC_EVENT
:
4363 ad1984a_touchsmart_automic(codec
);
4368 /* initialize jack-sensing, too */
4369 static int ad1984a_touchsmart_init(struct hda_codec
*codec
)
4372 ad1884a_hp_automute(codec
);
4373 ad1984a_touchsmart_automic(codec
);
4390 static const char * const ad1884a_models
[AD1884A_MODELS
] = {
4391 [AD1884A_DESKTOP
] = "desktop",
4392 [AD1884A_LAPTOP
] = "laptop",
4393 [AD1884A_MOBILE
] = "mobile",
4394 [AD1884A_THINKPAD
] = "thinkpad",
4395 [AD1984A_TOUCHSMART
] = "touchsmart",
4398 static struct snd_pci_quirk ad1884a_cfg_tbl
[] = {
4399 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE
),
4400 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP
),
4401 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE
),
4402 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE
),
4403 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP
),
4404 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP
),
4405 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP
),
4406 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE
),
4407 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD
),
4408 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART
),
4412 static int patch_ad1884a(struct hda_codec
*codec
)
4414 struct ad198x_spec
*spec
;
4415 int err
, board_config
;
4417 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4423 err
= snd_hda_attach_beep_device(codec
, 0x10);
4428 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
4430 spec
->multiout
.max_channels
= 2;
4431 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884a_dac_nids
);
4432 spec
->multiout
.dac_nids
= ad1884a_dac_nids
;
4433 spec
->multiout
.dig_out_nid
= AD1884A_SPDIF_OUT
;
4434 spec
->num_adc_nids
= ARRAY_SIZE(ad1884a_adc_nids
);
4435 spec
->adc_nids
= ad1884a_adc_nids
;
4436 spec
->capsrc_nids
= ad1884a_capsrc_nids
;
4437 spec
->input_mux
= &ad1884a_capture_source
;
4438 spec
->num_mixers
= 1;
4439 spec
->mixers
[0] = ad1884a_base_mixers
;
4440 spec
->num_init_verbs
= 1;
4441 spec
->init_verbs
[0] = ad1884a_init_verbs
;
4442 spec
->spdif_route
= 0;
4443 #ifdef CONFIG_SND_HDA_POWER_SAVE
4444 spec
->loopback
.amplist
= ad1884a_loopbacks
;
4446 codec
->patch_ops
= ad198x_patch_ops
;
4448 /* override some parameters */
4449 board_config
= snd_hda_check_board_config(codec
, AD1884A_MODELS
,
4452 switch (board_config
) {
4453 case AD1884A_LAPTOP
:
4454 spec
->mixers
[0] = ad1884a_laptop_mixers
;
4455 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1884a_laptop_verbs
;
4456 spec
->multiout
.dig_out_nid
= 0;
4457 codec
->patch_ops
.unsol_event
= ad1884a_laptop_unsol_event
;
4458 codec
->patch_ops
.init
= ad1884a_laptop_init
;
4459 /* set the upper-limit for mixer amp to 0dB for avoiding the
4460 * possible damage by overloading
4462 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4463 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4464 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4465 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4466 (1 << AC_AMPCAP_MUTE_SHIFT
));
4468 case AD1884A_MOBILE
:
4469 spec
->mixers
[0] = ad1884a_mobile_mixers
;
4470 spec
->init_verbs
[0] = ad1884a_mobile_verbs
;
4471 spec
->multiout
.dig_out_nid
= 0;
4472 codec
->patch_ops
.unsol_event
= ad1884a_hp_unsol_event
;
4473 codec
->patch_ops
.init
= ad1884a_hp_init
;
4474 /* set the upper-limit for mixer amp to 0dB for avoiding the
4475 * possible damage by overloading
4477 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4478 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4479 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4480 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4481 (1 << AC_AMPCAP_MUTE_SHIFT
));
4483 case AD1884A_THINKPAD
:
4484 spec
->mixers
[0] = ad1984a_thinkpad_mixers
;
4485 spec
->init_verbs
[spec
->num_init_verbs
++] =
4486 ad1984a_thinkpad_verbs
;
4487 spec
->multiout
.dig_out_nid
= 0;
4488 spec
->input_mux
= &ad1984a_thinkpad_capture_source
;
4489 codec
->patch_ops
.unsol_event
= ad1984a_thinkpad_unsol_event
;
4490 codec
->patch_ops
.init
= ad1984a_thinkpad_init
;
4492 case AD1984A_TOUCHSMART
:
4493 spec
->mixers
[0] = ad1984a_touchsmart_mixers
;
4494 spec
->init_verbs
[0] = ad1984a_touchsmart_verbs
;
4495 spec
->multiout
.dig_out_nid
= 0;
4496 codec
->patch_ops
.unsol_event
= ad1984a_touchsmart_unsol_event
;
4497 codec
->patch_ops
.init
= ad1984a_touchsmart_init
;
4498 /* set the upper-limit for mixer amp to 0dB for avoiding the
4499 * possible damage by overloading
4501 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4502 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4503 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4504 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4505 (1 << AC_AMPCAP_MUTE_SHIFT
));
4509 codec
->no_trigger_sense
= 1;
4510 codec
->no_sticky_stream
= 1;
4519 * port-A - front hp-out
4520 * port-B - front mic-in
4521 * port-C - rear line-in, shared surr-out (3stack)
4522 * port-D - rear line-out
4523 * port-E - rear mic-in, shared clfe-out (3stack)
4524 * port-F - rear surr-out (6stack)
4525 * port-G - rear clfe-out (6stack)
4528 static hda_nid_t ad1882_dac_nids
[3] = {
4532 static hda_nid_t ad1882_adc_nids
[2] = {
4536 static hda_nid_t ad1882_capsrc_nids
[2] = {
4540 #define AD1882_SPDIF_OUT 0x02
4542 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4543 static struct hda_input_mux ad1882_capture_source
= {
4546 { "Front Mic", 0x1 },
4554 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4555 static struct hda_input_mux ad1882a_capture_source
= {
4558 { "Front Mic", 0x1 },
4561 { "Digital Mic", 0x06 },
4566 static struct snd_kcontrol_new ad1882_base_mixers
[] = {
4567 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
4568 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
4569 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
4570 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
4571 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
4572 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
4573 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
4574 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
4576 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
4577 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
4578 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT
),
4579 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4580 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4581 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
4582 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
4584 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4585 /* The multiple "Capture Source" controls confuse alsamixer
4586 * So call somewhat different..
4588 /* .name = "Capture Source", */
4589 .name
= "Input Source",
4591 .info
= ad198x_mux_enum_info
,
4592 .get
= ad198x_mux_enum_get
,
4593 .put
= ad198x_mux_enum_put
,
4595 /* SPDIF controls */
4596 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
4598 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4599 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
4600 /* identical with ad1983 */
4601 .info
= ad1983_spdif_route_info
,
4602 .get
= ad1983_spdif_route_get
,
4603 .put
= ad1983_spdif_route_put
,
4608 static struct snd_kcontrol_new ad1882_loopback_mixers
[] = {
4609 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4610 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4611 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
4612 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
4613 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT
),
4614 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT
),
4615 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4616 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4620 static struct snd_kcontrol_new ad1882a_loopback_mixers
[] = {
4621 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4622 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4623 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
4624 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
4625 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
4626 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
4627 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4628 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4629 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT
),
4633 static struct snd_kcontrol_new ad1882_3stack_mixers
[] = {
4634 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
4635 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT
),
4636 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT
),
4638 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4639 .name
= "Channel Mode",
4640 .info
= ad198x_ch_mode_info
,
4641 .get
= ad198x_ch_mode_get
,
4642 .put
= ad198x_ch_mode_put
,
4647 static struct snd_kcontrol_new ad1882_6stack_mixers
[] = {
4648 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
4649 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT
),
4650 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT
),
4654 static struct hda_verb ad1882_ch2_init
[] = {
4655 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4656 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4657 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4658 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4659 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4660 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4664 static struct hda_verb ad1882_ch4_init
[] = {
4665 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4666 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4667 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4668 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4669 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4670 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4674 static struct hda_verb ad1882_ch6_init
[] = {
4675 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4676 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4677 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4678 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4679 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4680 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4684 static struct hda_channel_mode ad1882_modes
[3] = {
4685 { 2, ad1882_ch2_init
},
4686 { 4, ad1882_ch4_init
},
4687 { 6, ad1882_ch6_init
},
4691 * initialization verbs
4693 static struct hda_verb ad1882_init_verbs
[] = {
4694 /* DACs; mute as default */
4695 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4696 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4697 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4698 /* Port-A (HP) mixer */
4699 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4700 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4702 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4703 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4704 /* HP selector - select DAC2 */
4705 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x1},
4706 /* Port-D (Line-out) mixer */
4707 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4708 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4710 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4711 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4712 /* Mono-out mixer */
4713 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4714 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4716 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4717 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4718 /* Port-B (front mic) pin */
4719 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4720 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4721 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4722 /* Port-C (line-in) pin */
4723 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4724 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4725 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4726 /* Port-C mixer - mute as input */
4727 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4728 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4729 /* Port-E (mic-in) pin */
4730 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4731 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4732 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4733 /* Port-E mixer - mute as input */
4734 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4735 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4736 /* Port-F (surround) */
4737 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4738 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4740 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4741 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4742 /* Analog mixer; mute as default */
4743 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4744 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4745 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4746 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4747 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4748 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4749 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4750 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
4751 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
4752 /* Analog Mix output amp */
4753 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
4754 /* SPDIF output selector */
4755 {0x02, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4756 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
4757 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4761 #ifdef CONFIG_SND_HDA_POWER_SAVE
4762 static struct hda_amp_list ad1882_loopbacks
[] = {
4763 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
4764 { 0x20, HDA_INPUT
, 1 }, /* Mic */
4765 { 0x20, HDA_INPUT
, 4 }, /* Line */
4766 { 0x20, HDA_INPUT
, 6 }, /* CD */
4778 static const char * const ad1882_models
[AD1986A_MODELS
] = {
4779 [AD1882_3STACK
] = "3stack",
4780 [AD1882_6STACK
] = "6stack",
4784 static int patch_ad1882(struct hda_codec
*codec
)
4786 struct ad198x_spec
*spec
;
4787 int err
, board_config
;
4789 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4795 err
= snd_hda_attach_beep_device(codec
, 0x10);
4800 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
4802 spec
->multiout
.max_channels
= 6;
4803 spec
->multiout
.num_dacs
= 3;
4804 spec
->multiout
.dac_nids
= ad1882_dac_nids
;
4805 spec
->multiout
.dig_out_nid
= AD1882_SPDIF_OUT
;
4806 spec
->num_adc_nids
= ARRAY_SIZE(ad1882_adc_nids
);
4807 spec
->adc_nids
= ad1882_adc_nids
;
4808 spec
->capsrc_nids
= ad1882_capsrc_nids
;
4809 if (codec
->vendor_id
== 0x11d41882)
4810 spec
->input_mux
= &ad1882_capture_source
;
4812 spec
->input_mux
= &ad1882a_capture_source
;
4813 spec
->num_mixers
= 2;
4814 spec
->mixers
[0] = ad1882_base_mixers
;
4815 if (codec
->vendor_id
== 0x11d41882)
4816 spec
->mixers
[1] = ad1882_loopback_mixers
;
4818 spec
->mixers
[1] = ad1882a_loopback_mixers
;
4819 spec
->num_init_verbs
= 1;
4820 spec
->init_verbs
[0] = ad1882_init_verbs
;
4821 spec
->spdif_route
= 0;
4822 #ifdef CONFIG_SND_HDA_POWER_SAVE
4823 spec
->loopback
.amplist
= ad1882_loopbacks
;
4825 spec
->vmaster_nid
= 0x04;
4827 codec
->patch_ops
= ad198x_patch_ops
;
4829 /* override some parameters */
4830 board_config
= snd_hda_check_board_config(codec
, AD1882_MODELS
,
4831 ad1882_models
, NULL
);
4832 switch (board_config
) {
4835 spec
->num_mixers
= 3;
4836 spec
->mixers
[2] = ad1882_3stack_mixers
;
4837 spec
->channel_mode
= ad1882_modes
;
4838 spec
->num_channel_mode
= ARRAY_SIZE(ad1882_modes
);
4839 spec
->need_dac_fix
= 1;
4840 spec
->multiout
.max_channels
= 2;
4841 spec
->multiout
.num_dacs
= 1;
4844 spec
->num_mixers
= 3;
4845 spec
->mixers
[2] = ad1882_6stack_mixers
;
4849 codec
->no_trigger_sense
= 1;
4850 codec
->no_sticky_stream
= 1;
4859 static struct hda_codec_preset snd_hda_preset_analog
[] = {
4860 { .id
= 0x11d4184a, .name
= "AD1884A", .patch
= patch_ad1884a
},
4861 { .id
= 0x11d41882, .name
= "AD1882", .patch
= patch_ad1882
},
4862 { .id
= 0x11d41883, .name
= "AD1883", .patch
= patch_ad1884a
},
4863 { .id
= 0x11d41884, .name
= "AD1884", .patch
= patch_ad1884
},
4864 { .id
= 0x11d4194a, .name
= "AD1984A", .patch
= patch_ad1884a
},
4865 { .id
= 0x11d4194b, .name
= "AD1984B", .patch
= patch_ad1884a
},
4866 { .id
= 0x11d41981, .name
= "AD1981", .patch
= patch_ad1981
},
4867 { .id
= 0x11d41983, .name
= "AD1983", .patch
= patch_ad1983
},
4868 { .id
= 0x11d41984, .name
= "AD1984", .patch
= patch_ad1984
},
4869 { .id
= 0x11d41986, .name
= "AD1986A", .patch
= patch_ad1986a
},
4870 { .id
= 0x11d41988, .name
= "AD1988", .patch
= patch_ad1988
},
4871 { .id
= 0x11d4198b, .name
= "AD1988B", .patch
= patch_ad1988
},
4872 { .id
= 0x11d4882a, .name
= "AD1882A", .patch
= patch_ad1882
},
4873 { .id
= 0x11d4989a, .name
= "AD1989A", .patch
= patch_ad1988
},
4874 { .id
= 0x11d4989b, .name
= "AD1989B", .patch
= patch_ad1988
},
4878 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4880 MODULE_LICENSE("GPL");
4881 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4883 static struct hda_codec_preset_list analog_list
= {
4884 .preset
= snd_hda_preset_analog
,
4885 .owner
= THIS_MODULE
,
4888 static int __init
patch_analog_init(void)
4890 return snd_hda_add_codec_preset(&analog_list
);
4893 static void __exit
patch_analog_exit(void)
4895 snd_hda_delete_codec_preset(&analog_list
);
4898 module_init(patch_analog_init
)
4899 module_exit(patch_analog_exit
)