2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
26 #include <linux/module.h>
28 #include <sound/core.h>
29 #include "hda_codec.h"
30 #include "hda_local.h"
34 const struct snd_kcontrol_new
*mixers
[6];
36 unsigned int beep_amp
; /* beep amp value, set via set_beep_amp() */
37 const struct hda_verb
*init_verbs
[6]; /* initialization verbs
38 * don't forget NULL termination!
40 unsigned int num_init_verbs
;
43 struct hda_multi_out multiout
; /* playback set-up
44 * max_channels, dacs must be set
45 * dig_out_nid and hp_nid are optional
47 unsigned int cur_eapd
;
48 unsigned int need_dac_fix
;
50 const hda_nid_t
*alt_dac_nid
;
51 const struct hda_pcm_stream
*stream_analog_alt_playback
;
53 int num_active_streams
;
56 unsigned int num_adc_nids
;
57 const hda_nid_t
*adc_nids
;
58 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
61 const struct hda_input_mux
*input_mux
;
62 const hda_nid_t
*capsrc_nids
;
63 unsigned int cur_mux
[3];
66 const struct hda_channel_mode
*channel_mode
;
70 struct hda_pcm pcm_rec
[3]; /* used in alc_build_pcms() */
72 unsigned int spdif_route
;
74 /* dynamic controls, init_verbs and input_mux */
75 struct auto_pin_cfg autocfg
;
76 struct snd_array kctls
;
77 struct hda_input_mux private_imux
;
78 hda_nid_t private_dac_nids
[AUTO_CFG_MAX_OUTS
];
80 unsigned int jack_present
: 1;
81 unsigned int inv_jack_detect
: 1;/* inverted jack-detection */
82 unsigned int inv_eapd
: 1; /* inverted EAPD implementation */
83 unsigned int analog_beep
: 1; /* analog beep input present */
85 #ifdef CONFIG_SND_HDA_POWER_SAVE
86 struct hda_loopback_check loopback
;
88 /* for virtual master */
89 hda_nid_t vmaster_nid
;
90 const char * const *slave_vols
;
91 const char * const *slave_sws
;
95 * input MUX handling (common part)
97 static int ad198x_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
99 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
100 struct ad198x_spec
*spec
= codec
->spec
;
102 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
105 static int ad198x_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
107 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
108 struct ad198x_spec
*spec
= codec
->spec
;
109 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
111 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
115 static int ad198x_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
117 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
118 struct ad198x_spec
*spec
= codec
->spec
;
119 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
121 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
122 spec
->capsrc_nids
[adc_idx
],
123 &spec
->cur_mux
[adc_idx
]);
127 * initialization (common callbacks)
129 static int ad198x_init(struct hda_codec
*codec
)
131 struct ad198x_spec
*spec
= codec
->spec
;
134 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
135 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
139 static const char * const ad_slave_vols
[] = {
140 "Front Playback Volume",
141 "Surround Playback Volume",
142 "Center Playback Volume",
143 "LFE Playback Volume",
144 "Side Playback Volume",
145 "Headphone Playback Volume",
146 "Mono Playback Volume",
147 "Speaker Playback Volume",
148 "IEC958 Playback Volume",
152 static const char * const ad_slave_sws
[] = {
153 "Front Playback Switch",
154 "Surround Playback Switch",
155 "Center Playback Switch",
156 "LFE Playback Switch",
157 "Side Playback Switch",
158 "Headphone Playback Switch",
159 "Mono Playback Switch",
160 "Speaker Playback Switch",
161 "IEC958 Playback Switch",
165 static const char * const ad1988_6stack_fp_slave_vols
[] = {
166 "Front Playback Volume",
167 "Surround Playback Volume",
168 "Center Playback Volume",
169 "LFE Playback Volume",
170 "Side Playback Volume",
171 "IEC958 Playback Volume",
175 static const char * const ad1988_6stack_fp_slave_sws
[] = {
176 "Front Playback Switch",
177 "Surround Playback Switch",
178 "Center Playback Switch",
179 "LFE Playback Switch",
180 "Side Playback Switch",
181 "IEC958 Playback Switch",
184 static void ad198x_free_kctls(struct hda_codec
*codec
);
186 #ifdef CONFIG_SND_HDA_INPUT_BEEP
187 /* additional beep mixers; the actual parameters are overwritten at build */
188 static const struct snd_kcontrol_new ad_beep_mixer
[] = {
189 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT
),
190 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT
),
194 static const struct snd_kcontrol_new ad_beep2_mixer
[] = {
195 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT
),
196 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT
),
200 #define set_beep_amp(spec, nid, idx, dir) \
201 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
203 #define set_beep_amp(spec, nid, idx, dir) /* NOP */
206 static int ad198x_build_controls(struct hda_codec
*codec
)
208 struct ad198x_spec
*spec
= codec
->spec
;
209 struct snd_kcontrol
*kctl
;
213 for (i
= 0; i
< spec
->num_mixers
; i
++) {
214 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
218 if (spec
->multiout
.dig_out_nid
) {
219 err
= snd_hda_create_spdif_out_ctls(codec
,
220 spec
->multiout
.dig_out_nid
,
221 spec
->multiout
.dig_out_nid
);
224 err
= snd_hda_create_spdif_share_sw(codec
,
228 spec
->multiout
.share_spdif
= 1;
230 if (spec
->dig_in_nid
) {
231 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
236 /* create beep controls if needed */
237 #ifdef CONFIG_SND_HDA_INPUT_BEEP
238 if (spec
->beep_amp
) {
239 const struct snd_kcontrol_new
*knew
;
240 knew
= spec
->analog_beep
? ad_beep2_mixer
: ad_beep_mixer
;
241 for ( ; knew
->name
; knew
++) {
242 struct snd_kcontrol
*kctl
;
243 kctl
= snd_ctl_new1(knew
, codec
);
246 kctl
->private_value
= spec
->beep_amp
;
247 err
= snd_hda_ctl_add(codec
, 0, kctl
);
254 /* if we have no master control, let's create it */
255 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Volume")) {
256 unsigned int vmaster_tlv
[4];
257 snd_hda_set_vmaster_tlv(codec
, spec
->vmaster_nid
,
258 HDA_OUTPUT
, vmaster_tlv
);
259 err
= snd_hda_add_vmaster(codec
, "Master Playback Volume",
262 spec
->slave_vols
: ad_slave_vols
));
266 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Switch")) {
267 err
= snd_hda_add_vmaster(codec
, "Master Playback Switch",
270 spec
->slave_sws
: ad_slave_sws
));
275 ad198x_free_kctls(codec
); /* no longer needed */
277 /* assign Capture Source enums to NID */
278 kctl
= snd_hda_find_mixer_ctl(codec
, "Capture Source");
280 kctl
= snd_hda_find_mixer_ctl(codec
, "Input Source");
281 for (i
= 0; kctl
&& i
< kctl
->count
; i
++) {
282 err
= snd_hda_add_nid(codec
, kctl
, i
, spec
->capsrc_nids
[i
]);
287 /* assign IEC958 enums to NID */
288 kctl
= snd_hda_find_mixer_ctl(codec
,
289 SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source");
291 err
= snd_hda_add_nid(codec
, kctl
, 0,
292 spec
->multiout
.dig_out_nid
);
300 #ifdef CONFIG_SND_HDA_POWER_SAVE
301 static int ad198x_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
303 struct ad198x_spec
*spec
= codec
->spec
;
304 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
308 static void activate_ctl(struct hda_codec
*codec
, const char *name
, int active
)
310 struct snd_kcontrol
*ctl
= snd_hda_find_mixer_ctl(codec
, name
);
312 ctl
->vd
[0].access
&= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
313 ctl
->vd
[0].access
|= active
? 0 :
314 SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
315 ctl
->vd
[0].access
&= ~SNDRV_CTL_ELEM_ACCESS_WRITE
;
316 ctl
->vd
[0].access
|= active
?
317 SNDRV_CTL_ELEM_ACCESS_WRITE
: 0;
318 snd_ctl_notify(codec
->bus
->card
,
319 SNDRV_CTL_EVENT_MASK_INFO
, &ctl
->id
);
323 static void set_stream_active(struct hda_codec
*codec
, bool active
)
325 struct ad198x_spec
*spec
= codec
->spec
;
327 spec
->num_active_streams
++;
329 spec
->num_active_streams
--;
330 activate_ctl(codec
, "Independent HP", spec
->num_active_streams
== 0);
333 static int ad1988_independent_hp_info(struct snd_kcontrol
*kcontrol
,
334 struct snd_ctl_elem_info
*uinfo
)
336 static const char * const texts
[] = { "OFF", "ON", NULL
};
338 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
340 uinfo
->value
.enumerated
.items
= 2;
341 index
= uinfo
->value
.enumerated
.item
;
344 strcpy(uinfo
->value
.enumerated
.name
, texts
[index
]);
348 static int ad1988_independent_hp_get(struct snd_kcontrol
*kcontrol
,
349 struct snd_ctl_elem_value
*ucontrol
)
351 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
352 struct ad198x_spec
*spec
= codec
->spec
;
353 ucontrol
->value
.enumerated
.item
[0] = spec
->independent_hp
;
357 static int ad1988_independent_hp_put(struct snd_kcontrol
*kcontrol
,
358 struct snd_ctl_elem_value
*ucontrol
)
360 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
361 struct ad198x_spec
*spec
= codec
->spec
;
362 unsigned int select
= ucontrol
->value
.enumerated
.item
[0];
363 if (spec
->independent_hp
!= select
) {
364 spec
->independent_hp
= select
;
365 if (spec
->independent_hp
)
366 spec
->multiout
.hp_nid
= 0;
368 spec
->multiout
.hp_nid
= spec
->alt_dac_nid
[0];
375 * Analog playback callbacks
377 static int ad198x_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
378 struct hda_codec
*codec
,
379 struct snd_pcm_substream
*substream
)
381 struct ad198x_spec
*spec
= codec
->spec
;
383 set_stream_active(codec
, true);
384 err
= snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
387 set_stream_active(codec
, false);
393 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
394 struct hda_codec
*codec
,
395 unsigned int stream_tag
,
397 struct snd_pcm_substream
*substream
)
399 struct ad198x_spec
*spec
= codec
->spec
;
400 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
404 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
405 struct hda_codec
*codec
,
406 struct snd_pcm_substream
*substream
)
408 struct ad198x_spec
*spec
= codec
->spec
;
409 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
412 static int ad198x_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
413 struct hda_codec
*codec
,
414 struct snd_pcm_substream
*substream
)
416 set_stream_active(codec
, false);
420 static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
421 struct hda_codec
*codec
,
422 struct snd_pcm_substream
*substream
)
424 struct ad198x_spec
*spec
= codec
->spec
;
425 if (!spec
->independent_hp
)
427 set_stream_active(codec
, true);
431 static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
432 struct hda_codec
*codec
,
433 struct snd_pcm_substream
*substream
)
435 set_stream_active(codec
, false);
439 static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback
= {
444 .open
= ad1988_alt_playback_pcm_open
,
445 .close
= ad1988_alt_playback_pcm_close
452 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
453 struct hda_codec
*codec
,
454 struct snd_pcm_substream
*substream
)
456 struct ad198x_spec
*spec
= codec
->spec
;
457 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
460 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
461 struct hda_codec
*codec
,
462 struct snd_pcm_substream
*substream
)
464 struct ad198x_spec
*spec
= codec
->spec
;
465 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
468 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
469 struct hda_codec
*codec
,
470 unsigned int stream_tag
,
472 struct snd_pcm_substream
*substream
)
474 struct ad198x_spec
*spec
= codec
->spec
;
475 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
479 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
480 struct hda_codec
*codec
,
481 struct snd_pcm_substream
*substream
)
483 struct ad198x_spec
*spec
= codec
->spec
;
484 return snd_hda_multi_out_dig_cleanup(codec
, &spec
->multiout
);
490 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
491 struct hda_codec
*codec
,
492 unsigned int stream_tag
,
494 struct snd_pcm_substream
*substream
)
496 struct ad198x_spec
*spec
= codec
->spec
;
497 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
498 stream_tag
, 0, format
);
502 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
503 struct hda_codec
*codec
,
504 struct snd_pcm_substream
*substream
)
506 struct ad198x_spec
*spec
= codec
->spec
;
507 snd_hda_codec_cleanup_stream(codec
, spec
->adc_nids
[substream
->number
]);
513 static const struct hda_pcm_stream ad198x_pcm_analog_playback
= {
516 .channels_max
= 6, /* changed later */
517 .nid
= 0, /* fill later */
519 .open
= ad198x_playback_pcm_open
,
520 .prepare
= ad198x_playback_pcm_prepare
,
521 .cleanup
= ad198x_playback_pcm_cleanup
,
522 .close
= ad198x_playback_pcm_close
526 static const struct hda_pcm_stream ad198x_pcm_analog_capture
= {
530 .nid
= 0, /* fill later */
532 .prepare
= ad198x_capture_pcm_prepare
,
533 .cleanup
= ad198x_capture_pcm_cleanup
537 static const struct hda_pcm_stream ad198x_pcm_digital_playback
= {
541 .nid
= 0, /* fill later */
543 .open
= ad198x_dig_playback_pcm_open
,
544 .close
= ad198x_dig_playback_pcm_close
,
545 .prepare
= ad198x_dig_playback_pcm_prepare
,
546 .cleanup
= ad198x_dig_playback_pcm_cleanup
550 static const struct hda_pcm_stream ad198x_pcm_digital_capture
= {
554 /* NID is set in alc_build_pcms */
557 static int ad198x_build_pcms(struct hda_codec
*codec
)
559 struct ad198x_spec
*spec
= codec
->spec
;
560 struct hda_pcm
*info
= spec
->pcm_rec
;
563 codec
->pcm_info
= info
;
565 info
->name
= "AD198x Analog";
566 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_analog_playback
;
567 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->multiout
.max_channels
;
568 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
569 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_analog_capture
;
570 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_adc_nids
;
571 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
573 if (spec
->multiout
.dig_out_nid
) {
576 info
->name
= "AD198x Digital";
577 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
578 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_digital_playback
;
579 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
580 if (spec
->dig_in_nid
) {
581 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_digital_capture
;
582 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
586 if (spec
->alt_dac_nid
&& spec
->stream_analog_alt_playback
) {
588 info
= spec
->pcm_rec
+ 2;
589 info
->name
= "AD198x Headphone";
590 info
->pcm_type
= HDA_PCM_TYPE_AUDIO
;
591 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
592 *spec
->stream_analog_alt_playback
;
593 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
594 spec
->alt_dac_nid
[0];
600 static void ad198x_free_kctls(struct hda_codec
*codec
)
602 struct ad198x_spec
*spec
= codec
->spec
;
604 if (spec
->kctls
.list
) {
605 struct snd_kcontrol_new
*kctl
= spec
->kctls
.list
;
607 for (i
= 0; i
< spec
->kctls
.used
; i
++)
610 snd_array_free(&spec
->kctls
);
613 static void ad198x_power_eapd_write(struct hda_codec
*codec
, hda_nid_t front
,
616 struct ad198x_spec
*spec
= codec
->spec
;
617 if (snd_hda_query_pin_caps(codec
, front
) & AC_PINCAP_EAPD
)
618 snd_hda_codec_write(codec
, front
, 0, AC_VERB_SET_EAPD_BTLENABLE
,
619 !spec
->inv_eapd
? 0x00 : 0x02);
620 if (snd_hda_query_pin_caps(codec
, hp
) & AC_PINCAP_EAPD
)
621 snd_hda_codec_write(codec
, hp
, 0, AC_VERB_SET_EAPD_BTLENABLE
,
622 !spec
->inv_eapd
? 0x00 : 0x02);
625 static void ad198x_power_eapd(struct hda_codec
*codec
)
627 /* We currently only handle front, HP */
628 switch (codec
->vendor_id
) {
641 ad198x_power_eapd_write(codec
, 0x12, 0x11);
645 ad198x_power_eapd_write(codec
, 0x05, 0x06);
648 ad198x_power_eapd_write(codec
, 0x1b, 0x1a);
653 static void ad198x_shutup(struct hda_codec
*codec
)
655 snd_hda_shutup_pins(codec
);
656 ad198x_power_eapd(codec
);
659 static void ad198x_free(struct hda_codec
*codec
)
661 struct ad198x_spec
*spec
= codec
->spec
;
666 ad198x_shutup(codec
);
667 ad198x_free_kctls(codec
);
669 snd_hda_detach_beep_device(codec
);
673 static int ad198x_suspend(struct hda_codec
*codec
, pm_message_t state
)
675 ad198x_shutup(codec
);
680 static const struct hda_codec_ops ad198x_patch_ops
= {
681 .build_controls
= ad198x_build_controls
,
682 .build_pcms
= ad198x_build_pcms
,
685 #ifdef CONFIG_SND_HDA_POWER_SAVE
686 .check_power_status
= ad198x_check_power_status
,
689 .suspend
= ad198x_suspend
,
691 .reboot_notify
= ad198x_shutup
,
697 * the private value = nid
699 #define ad198x_eapd_info snd_ctl_boolean_mono_info
701 static int ad198x_eapd_get(struct snd_kcontrol
*kcontrol
,
702 struct snd_ctl_elem_value
*ucontrol
)
704 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
705 struct ad198x_spec
*spec
= codec
->spec
;
707 ucontrol
->value
.integer
.value
[0] = ! spec
->cur_eapd
;
709 ucontrol
->value
.integer
.value
[0] = spec
->cur_eapd
;
713 static int ad198x_eapd_put(struct snd_kcontrol
*kcontrol
,
714 struct snd_ctl_elem_value
*ucontrol
)
716 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
717 struct ad198x_spec
*spec
= codec
->spec
;
718 hda_nid_t nid
= kcontrol
->private_value
& 0xff;
720 eapd
= !!ucontrol
->value
.integer
.value
[0];
723 if (eapd
== spec
->cur_eapd
)
725 spec
->cur_eapd
= eapd
;
726 snd_hda_codec_write_cache(codec
, nid
,
727 0, AC_VERB_SET_EAPD_BTLENABLE
,
732 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
733 struct snd_ctl_elem_info
*uinfo
);
734 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
735 struct snd_ctl_elem_value
*ucontrol
);
736 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
737 struct snd_ctl_elem_value
*ucontrol
);
744 #define AD1986A_SPDIF_OUT 0x02
745 #define AD1986A_FRONT_DAC 0x03
746 #define AD1986A_SURR_DAC 0x04
747 #define AD1986A_CLFE_DAC 0x05
748 #define AD1986A_ADC 0x06
750 static const hda_nid_t ad1986a_dac_nids
[3] = {
751 AD1986A_FRONT_DAC
, AD1986A_SURR_DAC
, AD1986A_CLFE_DAC
753 static const hda_nid_t ad1986a_adc_nids
[1] = { AD1986A_ADC
};
754 static const hda_nid_t ad1986a_capsrc_nids
[1] = { 0x12 };
756 static const struct hda_input_mux ad1986a_capture_source
= {
770 static const struct hda_bind_ctls ad1986a_bind_pcm_vol
= {
771 .ops
= &snd_hda_bind_vol
,
773 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
774 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
775 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
780 static const struct hda_bind_ctls ad1986a_bind_pcm_sw
= {
781 .ops
= &snd_hda_bind_sw
,
783 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
784 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
785 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
793 static const struct snd_kcontrol_new ad1986a_mixers
[] = {
795 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
797 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol
),
798 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw
),
799 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
800 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
801 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
802 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
803 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT
),
804 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT
),
805 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT
),
806 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT
),
807 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT
),
808 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT
),
809 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
810 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
811 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
812 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
813 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
814 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
815 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
816 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
817 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
818 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT
),
819 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT
),
820 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
821 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
823 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
824 .name
= "Capture Source",
825 .info
= ad198x_mux_enum_info
,
826 .get
= ad198x_mux_enum_get
,
827 .put
= ad198x_mux_enum_put
,
829 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT
),
833 /* additional mixers for 3stack mode */
834 static const struct snd_kcontrol_new ad1986a_3st_mixers
[] = {
836 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
837 .name
= "Channel Mode",
838 .info
= ad198x_ch_mode_info
,
839 .get
= ad198x_ch_mode_get
,
840 .put
= ad198x_ch_mode_put
,
845 /* laptop model - 2ch only */
846 static const hda_nid_t ad1986a_laptop_dac_nids
[1] = { AD1986A_FRONT_DAC
};
848 /* master controls both pins 0x1a and 0x1b */
849 static const struct hda_bind_ctls ad1986a_laptop_master_vol
= {
850 .ops
= &snd_hda_bind_vol
,
852 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
853 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
858 static const struct hda_bind_ctls ad1986a_laptop_master_sw
= {
859 .ops
= &snd_hda_bind_sw
,
861 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
862 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
867 static const struct snd_kcontrol_new ad1986a_laptop_mixers
[] = {
868 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
869 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
870 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
871 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
872 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
873 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
874 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
875 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
876 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
877 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
878 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
879 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
880 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
882 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
883 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
884 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
885 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
887 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
888 .name
= "Capture Source",
889 .info
= ad198x_mux_enum_info
,
890 .get
= ad198x_mux_enum_get
,
891 .put
= ad198x_mux_enum_put
,
896 /* laptop-eapd model - 2ch only */
898 static const struct hda_input_mux ad1986a_laptop_eapd_capture_source
= {
902 { "Internal Mic", 0x4 },
907 static const struct hda_input_mux ad1986a_automic_capture_source
= {
915 static const struct snd_kcontrol_new ad1986a_laptop_master_mixers
[] = {
916 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
917 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
921 static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers
[] = {
922 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
923 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
924 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
925 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
926 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT
),
927 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
928 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
930 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
931 .name
= "Capture Source",
932 .info
= ad198x_mux_enum_info
,
933 .get
= ad198x_mux_enum_get
,
934 .put
= ad198x_mux_enum_put
,
937 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
938 .name
= "External Amplifier",
939 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x1b,
940 .info
= ad198x_eapd_info
,
941 .get
= ad198x_eapd_get
,
942 .put
= ad198x_eapd_put
,
943 .private_value
= 0x1b, /* port-D */
948 static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers
[] = {
949 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT
),
950 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT
),
954 /* re-connect the mic boost input according to the jack sensing */
955 static void ad1986a_automic(struct hda_codec
*codec
)
957 unsigned int present
;
958 present
= snd_hda_jack_detect(codec
, 0x1f);
959 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
960 snd_hda_codec_write(codec
, 0x0f, 0, AC_VERB_SET_CONNECT_SEL
,
964 #define AD1986A_MIC_EVENT 0x36
966 static void ad1986a_automic_unsol_event(struct hda_codec
*codec
,
969 if ((res
>> 26) != AD1986A_MIC_EVENT
)
971 ad1986a_automic(codec
);
974 static int ad1986a_automic_init(struct hda_codec
*codec
)
977 ad1986a_automic(codec
);
981 /* laptop-automute - 2ch only */
983 static void ad1986a_update_hp(struct hda_codec
*codec
)
985 struct ad198x_spec
*spec
= codec
->spec
;
988 if (spec
->jack_present
)
989 mute
= HDA_AMP_MUTE
; /* mute internal speaker */
991 /* unmute internal speaker if necessary */
992 mute
= snd_hda_codec_amp_read(codec
, 0x1a, 0, HDA_OUTPUT
, 0);
993 snd_hda_codec_amp_stereo(codec
, 0x1b, HDA_OUTPUT
, 0,
997 static void ad1986a_hp_automute(struct hda_codec
*codec
)
999 struct ad198x_spec
*spec
= codec
->spec
;
1001 spec
->jack_present
= snd_hda_jack_detect(codec
, 0x1a);
1002 if (spec
->inv_jack_detect
)
1003 spec
->jack_present
= !spec
->jack_present
;
1004 ad1986a_update_hp(codec
);
1007 #define AD1986A_HP_EVENT 0x37
1009 static void ad1986a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
1011 if ((res
>> 26) != AD1986A_HP_EVENT
)
1013 ad1986a_hp_automute(codec
);
1016 static int ad1986a_hp_init(struct hda_codec
*codec
)
1019 ad1986a_hp_automute(codec
);
1023 /* bind hp and internal speaker mute (with plug check) */
1024 static int ad1986a_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
1025 struct snd_ctl_elem_value
*ucontrol
)
1027 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1028 long *valp
= ucontrol
->value
.integer
.value
;
1031 change
= snd_hda_codec_amp_update(codec
, 0x1a, 0, HDA_OUTPUT
, 0,
1033 valp
[0] ? 0 : HDA_AMP_MUTE
);
1034 change
|= snd_hda_codec_amp_update(codec
, 0x1a, 1, HDA_OUTPUT
, 0,
1036 valp
[1] ? 0 : HDA_AMP_MUTE
);
1038 ad1986a_update_hp(codec
);
1042 static const struct snd_kcontrol_new ad1986a_automute_master_mixers
[] = {
1043 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
1045 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1046 .name
= "Master Playback Switch",
1047 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
1048 .info
= snd_hda_mixer_amp_switch_info
,
1049 .get
= snd_hda_mixer_amp_switch_get
,
1050 .put
= ad1986a_hp_master_sw_put
,
1051 .private_value
= HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
1058 * initialization verbs
1060 static const struct hda_verb ad1986a_init_verbs
[] = {
1061 /* Front, Surround, CLFE DAC; mute as default */
1062 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1063 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1064 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1066 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1067 /* HP, Line-Out, Surround, CLFE selectors */
1068 {0x0a, AC_VERB_SET_CONNECT_SEL
, 0x0},
1069 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0},
1070 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
1071 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1073 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x0},
1074 /* Mic selector: Mic 1/2 pin */
1075 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
1076 /* Line-in selector: Line-in */
1077 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x0},
1079 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x0},
1080 /* Record selector: mic */
1081 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x0},
1082 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
1083 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1084 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1085 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1086 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1087 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1089 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x0},
1090 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
1091 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1092 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1093 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1094 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1095 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1097 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1098 /* Front, Surround, CLFE Pins */
1099 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1100 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1101 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1103 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1105 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1106 /* Line, Aux, CD, Beep-In Pin */
1107 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1108 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1109 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1110 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1111 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1115 static const struct hda_verb ad1986a_ch2_init
[] = {
1116 /* Surround out -> Line In */
1117 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1118 /* Line-in selectors */
1119 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x1 },
1120 /* CLFE -> Mic in */
1121 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1122 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1123 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
1127 static const struct hda_verb ad1986a_ch4_init
[] = {
1128 /* Surround out -> Surround */
1129 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1130 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1131 /* CLFE -> Mic in */
1132 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1133 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
1137 static const struct hda_verb ad1986a_ch6_init
[] = {
1138 /* Surround out -> Surround out */
1139 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1140 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1142 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1143 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0 },
1147 static const struct hda_channel_mode ad1986a_modes
[3] = {
1148 { 2, ad1986a_ch2_init
},
1149 { 4, ad1986a_ch4_init
},
1150 { 6, ad1986a_ch6_init
},
1153 /* eapd initialization */
1154 static const struct hda_verb ad1986a_eapd_init_verbs
[] = {
1155 {0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
1159 static const struct hda_verb ad1986a_automic_verbs
[] = {
1160 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1161 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1162 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1163 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
1164 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_MIC_EVENT
},
1168 /* Ultra initialization */
1169 static const struct hda_verb ad1986a_ultra_init
[] = {
1170 /* eapd initialization */
1171 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
1172 /* CLFE -> Mic in */
1173 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x2 },
1174 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1175 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
1179 /* pin sensing on HP jack */
1180 static const struct hda_verb ad1986a_hp_init_verbs
[] = {
1181 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_HP_EVENT
},
1185 static void ad1986a_samsung_p50_unsol_event(struct hda_codec
*codec
,
1188 switch (res
>> 26) {
1189 case AD1986A_HP_EVENT
:
1190 ad1986a_hp_automute(codec
);
1192 case AD1986A_MIC_EVENT
:
1193 ad1986a_automic(codec
);
1198 static int ad1986a_samsung_p50_init(struct hda_codec
*codec
)
1201 ad1986a_hp_automute(codec
);
1202 ad1986a_automic(codec
);
1212 AD1986A_LAPTOP_EAPD
,
1213 AD1986A_LAPTOP_AUTOMUTE
,
1216 AD1986A_SAMSUNG_P50
,
1220 static const char * const ad1986a_models
[AD1986A_MODELS
] = {
1221 [AD1986A_6STACK
] = "6stack",
1222 [AD1986A_3STACK
] = "3stack",
1223 [AD1986A_LAPTOP
] = "laptop",
1224 [AD1986A_LAPTOP_EAPD
] = "laptop-eapd",
1225 [AD1986A_LAPTOP_AUTOMUTE
] = "laptop-automute",
1226 [AD1986A_ULTRA
] = "ultra",
1227 [AD1986A_SAMSUNG
] = "samsung",
1228 [AD1986A_SAMSUNG_P50
] = "samsung-p50",
1231 static const struct snd_pci_quirk ad1986a_cfg_tbl
[] = {
1232 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD
),
1233 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD
),
1234 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD
),
1235 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD
),
1236 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD
),
1237 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD
),
1238 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD
),
1239 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD
),
1240 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP
),
1241 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK
),
1242 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK
),
1243 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP
),
1244 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK
),
1245 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK
),
1246 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK
),
1247 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK
),
1248 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK
),
1249 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK
),
1250 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP
),
1251 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50
),
1252 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA
),
1253 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG
),
1254 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK
),
1255 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP
),
1256 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK
),
1257 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE
),
1258 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP
),
1262 #ifdef CONFIG_SND_HDA_POWER_SAVE
1263 static const struct hda_amp_list ad1986a_loopbacks
[] = {
1264 { 0x13, HDA_OUTPUT
, 0 }, /* Mic */
1265 { 0x14, HDA_OUTPUT
, 0 }, /* Phone */
1266 { 0x15, HDA_OUTPUT
, 0 }, /* CD */
1267 { 0x16, HDA_OUTPUT
, 0 }, /* Aux */
1268 { 0x17, HDA_OUTPUT
, 0 }, /* Line */
1273 static int is_jack_available(struct hda_codec
*codec
, hda_nid_t nid
)
1275 unsigned int conf
= snd_hda_codec_get_pincfg(codec
, nid
);
1276 return get_defcfg_connect(conf
) != AC_JACK_PORT_NONE
;
1279 static int patch_ad1986a(struct hda_codec
*codec
)
1281 struct ad198x_spec
*spec
;
1282 int err
, board_config
;
1284 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1290 err
= snd_hda_attach_beep_device(codec
, 0x19);
1295 set_beep_amp(spec
, 0x18, 0, HDA_OUTPUT
);
1297 spec
->multiout
.max_channels
= 6;
1298 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1986a_dac_nids
);
1299 spec
->multiout
.dac_nids
= ad1986a_dac_nids
;
1300 spec
->multiout
.dig_out_nid
= AD1986A_SPDIF_OUT
;
1301 spec
->num_adc_nids
= 1;
1302 spec
->adc_nids
= ad1986a_adc_nids
;
1303 spec
->capsrc_nids
= ad1986a_capsrc_nids
;
1304 spec
->input_mux
= &ad1986a_capture_source
;
1305 spec
->num_mixers
= 1;
1306 spec
->mixers
[0] = ad1986a_mixers
;
1307 spec
->num_init_verbs
= 1;
1308 spec
->init_verbs
[0] = ad1986a_init_verbs
;
1309 #ifdef CONFIG_SND_HDA_POWER_SAVE
1310 spec
->loopback
.amplist
= ad1986a_loopbacks
;
1312 spec
->vmaster_nid
= 0x1b;
1313 spec
->inv_eapd
= 1; /* AD1986A has the inverted EAPD implementation */
1315 codec
->patch_ops
= ad198x_patch_ops
;
1317 /* override some parameters */
1318 board_config
= snd_hda_check_board_config(codec
, AD1986A_MODELS
,
1321 switch (board_config
) {
1322 case AD1986A_3STACK
:
1323 spec
->num_mixers
= 2;
1324 spec
->mixers
[1] = ad1986a_3st_mixers
;
1325 spec
->num_init_verbs
= 2;
1326 spec
->init_verbs
[1] = ad1986a_ch2_init
;
1327 spec
->channel_mode
= ad1986a_modes
;
1328 spec
->num_channel_mode
= ARRAY_SIZE(ad1986a_modes
);
1329 spec
->need_dac_fix
= 1;
1330 spec
->multiout
.max_channels
= 2;
1331 spec
->multiout
.num_dacs
= 1;
1333 case AD1986A_LAPTOP
:
1334 spec
->mixers
[0] = ad1986a_laptop_mixers
;
1335 spec
->multiout
.max_channels
= 2;
1336 spec
->multiout
.num_dacs
= 1;
1337 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1339 case AD1986A_LAPTOP_EAPD
:
1340 spec
->num_mixers
= 3;
1341 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1342 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1343 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1344 spec
->num_init_verbs
= 2;
1345 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1346 spec
->multiout
.max_channels
= 2;
1347 spec
->multiout
.num_dacs
= 1;
1348 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1349 if (!is_jack_available(codec
, 0x25))
1350 spec
->multiout
.dig_out_nid
= 0;
1351 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1353 case AD1986A_SAMSUNG
:
1354 spec
->num_mixers
= 2;
1355 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1356 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1357 spec
->num_init_verbs
= 3;
1358 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1359 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1360 spec
->multiout
.max_channels
= 2;
1361 spec
->multiout
.num_dacs
= 1;
1362 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1363 if (!is_jack_available(codec
, 0x25))
1364 spec
->multiout
.dig_out_nid
= 0;
1365 spec
->input_mux
= &ad1986a_automic_capture_source
;
1366 codec
->patch_ops
.unsol_event
= ad1986a_automic_unsol_event
;
1367 codec
->patch_ops
.init
= ad1986a_automic_init
;
1369 case AD1986A_SAMSUNG_P50
:
1370 spec
->num_mixers
= 2;
1371 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1372 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1373 spec
->num_init_verbs
= 4;
1374 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1375 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1376 spec
->init_verbs
[3] = ad1986a_hp_init_verbs
;
1377 spec
->multiout
.max_channels
= 2;
1378 spec
->multiout
.num_dacs
= 1;
1379 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1380 if (!is_jack_available(codec
, 0x25))
1381 spec
->multiout
.dig_out_nid
= 0;
1382 spec
->input_mux
= &ad1986a_automic_capture_source
;
1383 codec
->patch_ops
.unsol_event
= ad1986a_samsung_p50_unsol_event
;
1384 codec
->patch_ops
.init
= ad1986a_samsung_p50_init
;
1386 case AD1986A_LAPTOP_AUTOMUTE
:
1387 spec
->num_mixers
= 3;
1388 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1389 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1390 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1391 spec
->num_init_verbs
= 3;
1392 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1393 spec
->init_verbs
[2] = ad1986a_hp_init_verbs
;
1394 spec
->multiout
.max_channels
= 2;
1395 spec
->multiout
.num_dacs
= 1;
1396 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1397 if (!is_jack_available(codec
, 0x25))
1398 spec
->multiout
.dig_out_nid
= 0;
1399 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1400 codec
->patch_ops
.unsol_event
= ad1986a_hp_unsol_event
;
1401 codec
->patch_ops
.init
= ad1986a_hp_init
;
1402 /* Lenovo N100 seems to report the reversed bit
1403 * for HP jack-sensing
1405 spec
->inv_jack_detect
= 1;
1408 spec
->mixers
[0] = ad1986a_laptop_eapd_mixers
;
1409 spec
->num_init_verbs
= 2;
1410 spec
->init_verbs
[1] = ad1986a_ultra_init
;
1411 spec
->multiout
.max_channels
= 2;
1412 spec
->multiout
.num_dacs
= 1;
1413 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1414 spec
->multiout
.dig_out_nid
= 0;
1418 /* AD1986A has a hardware problem that it can't share a stream
1419 * with multiple output pins. The copy of front to surrounds
1420 * causes noisy or silent outputs at a certain timing, e.g.
1421 * changing the volume.
1422 * So, let's disable the shared stream.
1424 spec
->multiout
.no_share_stream
= 1;
1426 codec
->no_trigger_sense
= 1;
1427 codec
->no_sticky_stream
= 1;
1436 #define AD1983_SPDIF_OUT 0x02
1437 #define AD1983_DAC 0x03
1438 #define AD1983_ADC 0x04
1440 static const hda_nid_t ad1983_dac_nids
[1] = { AD1983_DAC
};
1441 static const hda_nid_t ad1983_adc_nids
[1] = { AD1983_ADC
};
1442 static const hda_nid_t ad1983_capsrc_nids
[1] = { 0x15 };
1444 static const struct hda_input_mux ad1983_capture_source
= {
1450 { "Mix Mono", 0x3 },
1455 * SPDIF playback route
1457 static int ad1983_spdif_route_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1459 static const char * const texts
[] = { "PCM", "ADC" };
1461 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1463 uinfo
->value
.enumerated
.items
= 2;
1464 if (uinfo
->value
.enumerated
.item
> 1)
1465 uinfo
->value
.enumerated
.item
= 1;
1466 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1470 static int ad1983_spdif_route_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1472 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1473 struct ad198x_spec
*spec
= codec
->spec
;
1475 ucontrol
->value
.enumerated
.item
[0] = spec
->spdif_route
;
1479 static int ad1983_spdif_route_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1481 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1482 struct ad198x_spec
*spec
= codec
->spec
;
1484 if (ucontrol
->value
.enumerated
.item
[0] > 1)
1486 if (spec
->spdif_route
!= ucontrol
->value
.enumerated
.item
[0]) {
1487 spec
->spdif_route
= ucontrol
->value
.enumerated
.item
[0];
1488 snd_hda_codec_write_cache(codec
, spec
->multiout
.dig_out_nid
, 0,
1489 AC_VERB_SET_CONNECT_SEL
,
1496 static const struct snd_kcontrol_new ad1983_mixers
[] = {
1497 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1498 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1499 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1500 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1501 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1502 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1503 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1504 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1505 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1506 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1507 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1508 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1509 HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT
),
1510 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1511 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1513 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1514 .name
= "Capture Source",
1515 .info
= ad198x_mux_enum_info
,
1516 .get
= ad198x_mux_enum_get
,
1517 .put
= ad198x_mux_enum_put
,
1520 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1521 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1522 .info
= ad1983_spdif_route_info
,
1523 .get
= ad1983_spdif_route_get
,
1524 .put
= ad1983_spdif_route_put
,
1529 static const struct hda_verb ad1983_init_verbs
[] = {
1530 /* Front, HP, Mono; mute as default */
1531 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1532 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1533 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1534 /* Beep, PCM, Mic, Line-In: mute */
1535 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1536 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1537 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1538 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1539 /* Front, HP selectors; from Mix */
1540 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1541 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1542 /* Mono selector; from Mix */
1543 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1544 /* Mic selector; Mic */
1545 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
1546 /* Line-in selector: Line-in */
1547 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1548 /* Mic boost: 0dB */
1549 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1550 /* Record selector: mic */
1551 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1552 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1553 /* SPDIF route: PCM */
1554 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1556 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1558 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1560 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1562 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1564 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1568 #ifdef CONFIG_SND_HDA_POWER_SAVE
1569 static const struct hda_amp_list ad1983_loopbacks
[] = {
1570 { 0x12, HDA_OUTPUT
, 0 }, /* Mic */
1571 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1576 static int patch_ad1983(struct hda_codec
*codec
)
1578 struct ad198x_spec
*spec
;
1581 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1587 err
= snd_hda_attach_beep_device(codec
, 0x10);
1592 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
1594 spec
->multiout
.max_channels
= 2;
1595 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1983_dac_nids
);
1596 spec
->multiout
.dac_nids
= ad1983_dac_nids
;
1597 spec
->multiout
.dig_out_nid
= AD1983_SPDIF_OUT
;
1598 spec
->num_adc_nids
= 1;
1599 spec
->adc_nids
= ad1983_adc_nids
;
1600 spec
->capsrc_nids
= ad1983_capsrc_nids
;
1601 spec
->input_mux
= &ad1983_capture_source
;
1602 spec
->num_mixers
= 1;
1603 spec
->mixers
[0] = ad1983_mixers
;
1604 spec
->num_init_verbs
= 1;
1605 spec
->init_verbs
[0] = ad1983_init_verbs
;
1606 spec
->spdif_route
= 0;
1607 #ifdef CONFIG_SND_HDA_POWER_SAVE
1608 spec
->loopback
.amplist
= ad1983_loopbacks
;
1610 spec
->vmaster_nid
= 0x05;
1612 codec
->patch_ops
= ad198x_patch_ops
;
1614 codec
->no_trigger_sense
= 1;
1615 codec
->no_sticky_stream
= 1;
1622 * AD1981 HD specific
1625 #define AD1981_SPDIF_OUT 0x02
1626 #define AD1981_DAC 0x03
1627 #define AD1981_ADC 0x04
1629 static const hda_nid_t ad1981_dac_nids
[1] = { AD1981_DAC
};
1630 static const hda_nid_t ad1981_adc_nids
[1] = { AD1981_ADC
};
1631 static const hda_nid_t ad1981_capsrc_nids
[1] = { 0x15 };
1633 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1634 static const struct hda_input_mux ad1981_capture_source
= {
1637 { "Front Mic", 0x0 },
1640 { "Mix Mono", 0x3 },
1647 static const struct snd_kcontrol_new ad1981_mixers
[] = {
1648 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1649 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1650 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1651 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1652 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1653 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1654 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1655 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1656 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1657 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1658 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1659 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1660 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
1661 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
1662 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1663 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1664 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1665 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1666 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1667 HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT
),
1668 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1669 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1671 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1672 .name
= "Capture Source",
1673 .info
= ad198x_mux_enum_info
,
1674 .get
= ad198x_mux_enum_get
,
1675 .put
= ad198x_mux_enum_put
,
1677 /* identical with AD1983 */
1679 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1680 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1681 .info
= ad1983_spdif_route_info
,
1682 .get
= ad1983_spdif_route_get
,
1683 .put
= ad1983_spdif_route_put
,
1688 static const struct hda_verb ad1981_init_verbs
[] = {
1689 /* Front, HP, Mono; mute as default */
1690 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1691 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1692 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1693 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1694 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1695 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1696 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1697 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1698 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1699 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1700 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1701 /* Front, HP selectors; from Mix */
1702 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1703 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1704 /* Mono selector; from Mix */
1705 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1706 /* Mic Mixer; select Front Mic */
1707 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1708 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1709 /* Mic boost: 0dB */
1710 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1711 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1712 /* Record selector: Front mic */
1713 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1714 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1715 /* SPDIF route: PCM */
1716 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1718 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1720 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1722 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1723 /* Front & Rear Mic Pins */
1724 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1725 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1727 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1729 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00},
1730 /* Line-Out as Input: disabled */
1731 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1735 #ifdef CONFIG_SND_HDA_POWER_SAVE
1736 static const struct hda_amp_list ad1981_loopbacks
[] = {
1737 { 0x12, HDA_OUTPUT
, 0 }, /* Front Mic */
1738 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1739 { 0x1b, HDA_OUTPUT
, 0 }, /* Aux */
1740 { 0x1c, HDA_OUTPUT
, 0 }, /* Mic */
1741 { 0x1d, HDA_OUTPUT
, 0 }, /* CD */
1747 * Patch for HP nx6320
1749 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1750 * speaker output enabled _and_ mute-LED off.
1753 #define AD1981_HP_EVENT 0x37
1754 #define AD1981_MIC_EVENT 0x38
1756 static const struct hda_verb ad1981_hp_init_verbs
[] = {
1757 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 }, /* default off */
1758 /* pin sensing on HP and Mic jacks */
1759 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1760 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1764 /* turn on/off EAPD (+ mute HP) as a master switch */
1765 static int ad1981_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
1766 struct snd_ctl_elem_value
*ucontrol
)
1768 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1769 struct ad198x_spec
*spec
= codec
->spec
;
1771 if (! ad198x_eapd_put(kcontrol
, ucontrol
))
1773 /* change speaker pin appropriately */
1774 snd_hda_codec_write(codec
, 0x05, 0,
1775 AC_VERB_SET_PIN_WIDGET_CONTROL
,
1776 spec
->cur_eapd
? PIN_OUT
: 0);
1777 /* toggle HP mute appropriately */
1778 snd_hda_codec_amp_stereo(codec
, 0x06, HDA_OUTPUT
, 0,
1780 spec
->cur_eapd
? 0 : HDA_AMP_MUTE
);
1784 /* bind volumes of both NID 0x05 and 0x06 */
1785 static const struct hda_bind_ctls ad1981_hp_bind_master_vol
= {
1786 .ops
= &snd_hda_bind_vol
,
1788 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT
),
1789 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT
),
1794 /* mute internal speaker if HP is plugged */
1795 static void ad1981_hp_automute(struct hda_codec
*codec
)
1797 unsigned int present
;
1799 present
= snd_hda_jack_detect(codec
, 0x06);
1800 snd_hda_codec_amp_stereo(codec
, 0x05, HDA_OUTPUT
, 0,
1801 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
1804 /* toggle input of built-in and mic jack appropriately */
1805 static void ad1981_hp_automic(struct hda_codec
*codec
)
1807 static const struct hda_verb mic_jack_on
[] = {
1808 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1809 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1812 static const struct hda_verb mic_jack_off
[] = {
1813 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1814 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1817 unsigned int present
;
1819 present
= snd_hda_jack_detect(codec
, 0x08);
1821 snd_hda_sequence_write(codec
, mic_jack_on
);
1823 snd_hda_sequence_write(codec
, mic_jack_off
);
1826 /* unsolicited event for HP jack sensing */
1827 static void ad1981_hp_unsol_event(struct hda_codec
*codec
,
1832 case AD1981_HP_EVENT
:
1833 ad1981_hp_automute(codec
);
1835 case AD1981_MIC_EVENT
:
1836 ad1981_hp_automic(codec
);
1841 static const struct hda_input_mux ad1981_hp_capture_source
= {
1845 { "Docking-Station", 0x1 },
1850 static const struct snd_kcontrol_new ad1981_hp_mixers
[] = {
1851 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol
),
1853 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1854 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x05,
1855 .name
= "Master Playback Switch",
1856 .info
= ad198x_eapd_info
,
1857 .get
= ad198x_eapd_get
,
1858 .put
= ad1981_hp_master_sw_put
,
1859 .private_value
= 0x05,
1861 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1862 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1864 /* FIXME: analog mic/line loopback doesn't work with my tests...
1865 * (although recording is OK)
1867 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1868 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1869 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1870 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1871 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1872 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1873 /* FIXME: does this laptop have analog CD connection? */
1874 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1875 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1877 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1878 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT
),
1879 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1880 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1882 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1883 .name
= "Capture Source",
1884 .info
= ad198x_mux_enum_info
,
1885 .get
= ad198x_mux_enum_get
,
1886 .put
= ad198x_mux_enum_put
,
1891 /* initialize jack-sensing, too */
1892 static int ad1981_hp_init(struct hda_codec
*codec
)
1895 ad1981_hp_automute(codec
);
1896 ad1981_hp_automic(codec
);
1900 /* configuration for Toshiba Laptops */
1901 static const struct hda_verb ad1981_toshiba_init_verbs
[] = {
1902 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x01 }, /* default on */
1903 /* pin sensing on HP and Mic jacks */
1904 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1905 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1909 static const struct snd_kcontrol_new ad1981_toshiba_mixers
[] = {
1910 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT
),
1911 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT
),
1915 /* configuration for Lenovo Thinkpad T60 */
1916 static const struct snd_kcontrol_new ad1981_thinkpad_mixers
[] = {
1917 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1918 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1919 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1920 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1921 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1922 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1923 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1924 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1925 HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT
),
1926 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1927 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1929 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1930 .name
= "Capture Source",
1931 .info
= ad198x_mux_enum_info
,
1932 .get
= ad198x_mux_enum_get
,
1933 .put
= ad198x_mux_enum_put
,
1935 /* identical with AD1983 */
1937 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1938 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1939 .info
= ad1983_spdif_route_info
,
1940 .get
= ad1983_spdif_route_get
,
1941 .put
= ad1983_spdif_route_put
,
1946 static const struct hda_input_mux ad1981_thinkpad_capture_source
= {
1964 static const char * const ad1981_models
[AD1981_MODELS
] = {
1966 [AD1981_THINKPAD
] = "thinkpad",
1967 [AD1981_BASIC
] = "basic",
1968 [AD1981_TOSHIBA
] = "toshiba"
1971 static const struct snd_pci_quirk ad1981_cfg_tbl
[] = {
1972 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD
),
1973 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD
),
1975 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP
),
1976 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA
),
1977 /* Lenovo Thinkpad T60/X60/Z6xx */
1978 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD
),
1979 /* HP nx6320 (reversed SSID, H/W bug) */
1980 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP
),
1984 static int patch_ad1981(struct hda_codec
*codec
)
1986 struct ad198x_spec
*spec
;
1987 int err
, board_config
;
1989 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1995 err
= snd_hda_attach_beep_device(codec
, 0x10);
2000 set_beep_amp(spec
, 0x0d, 0, HDA_OUTPUT
);
2002 spec
->multiout
.max_channels
= 2;
2003 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1981_dac_nids
);
2004 spec
->multiout
.dac_nids
= ad1981_dac_nids
;
2005 spec
->multiout
.dig_out_nid
= AD1981_SPDIF_OUT
;
2006 spec
->num_adc_nids
= 1;
2007 spec
->adc_nids
= ad1981_adc_nids
;
2008 spec
->capsrc_nids
= ad1981_capsrc_nids
;
2009 spec
->input_mux
= &ad1981_capture_source
;
2010 spec
->num_mixers
= 1;
2011 spec
->mixers
[0] = ad1981_mixers
;
2012 spec
->num_init_verbs
= 1;
2013 spec
->init_verbs
[0] = ad1981_init_verbs
;
2014 spec
->spdif_route
= 0;
2015 #ifdef CONFIG_SND_HDA_POWER_SAVE
2016 spec
->loopback
.amplist
= ad1981_loopbacks
;
2018 spec
->vmaster_nid
= 0x05;
2020 codec
->patch_ops
= ad198x_patch_ops
;
2022 /* override some parameters */
2023 board_config
= snd_hda_check_board_config(codec
, AD1981_MODELS
,
2026 switch (board_config
) {
2028 spec
->mixers
[0] = ad1981_hp_mixers
;
2029 spec
->num_init_verbs
= 2;
2030 spec
->init_verbs
[1] = ad1981_hp_init_verbs
;
2031 if (!is_jack_available(codec
, 0x0a))
2032 spec
->multiout
.dig_out_nid
= 0;
2033 spec
->input_mux
= &ad1981_hp_capture_source
;
2035 codec
->patch_ops
.init
= ad1981_hp_init
;
2036 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
2037 /* set the upper-limit for mixer amp to 0dB for avoiding the
2038 * possible damage by overloading
2040 snd_hda_override_amp_caps(codec
, 0x11, HDA_INPUT
,
2041 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
2042 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
2043 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
2044 (1 << AC_AMPCAP_MUTE_SHIFT
));
2046 case AD1981_THINKPAD
:
2047 spec
->mixers
[0] = ad1981_thinkpad_mixers
;
2048 spec
->input_mux
= &ad1981_thinkpad_capture_source
;
2049 /* set the upper-limit for mixer amp to 0dB for avoiding the
2050 * possible damage by overloading
2052 snd_hda_override_amp_caps(codec
, 0x11, HDA_INPUT
,
2053 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
2054 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
2055 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
2056 (1 << AC_AMPCAP_MUTE_SHIFT
));
2058 case AD1981_TOSHIBA
:
2059 spec
->mixers
[0] = ad1981_hp_mixers
;
2060 spec
->mixers
[1] = ad1981_toshiba_mixers
;
2061 spec
->num_init_verbs
= 2;
2062 spec
->init_verbs
[1] = ad1981_toshiba_init_verbs
;
2063 spec
->multiout
.dig_out_nid
= 0;
2064 spec
->input_mux
= &ad1981_hp_capture_source
;
2065 codec
->patch_ops
.init
= ad1981_hp_init
;
2066 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
2070 codec
->no_trigger_sense
= 1;
2071 codec
->no_sticky_stream
= 1;
2080 * Output pins and routes
2082 * Pin Mix Sel DAC (*)
2083 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
2084 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
2085 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
2086 * port-D 0x12 (mute/hp) <- 0x29 <- 04
2087 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
2088 * port-F 0x16 (mute) <- 0x2a <- 06
2089 * port-G 0x24 (mute) <- 0x27 <- 05
2090 * port-H 0x25 (mute) <- 0x28 <- 0a
2091 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
2093 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
2094 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
2096 * Input pins and routes
2098 * pin boost mix input # / adc input #
2099 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
2100 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
2101 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
2102 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
2103 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
2104 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
2105 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
2106 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2110 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2111 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2113 * Inputs of Analog Mix (0x20)
2114 * 0:Port-B (front mic)
2115 * 1:Port-C/G/H (line-in)
2117 * 3:Port-D (line-in/2)
2118 * 4:Port-E/G/H (mic-in)
2119 * 5:Port-F (mic2-in)
2125 * 1:Port-B (front mic-in)
2126 * 2:Port-C (line-in)
2127 * 3:Port-F (mic2-in)
2132 * 8:Port-D (line-in/2)
2135 * Proposed pin assignments by the datasheet
2138 * Port-A front headphone
2148 * Port-A front headphone
2150 * C rear line-in/surround
2152 * E rear mic-in/CLFE
2158 * D internal speaker (with EAPD)
2159 * E/F quad mic array
2175 /* reivision id to check workarounds */
2176 #define AD1988A_REV2 0x100200
2178 #define is_rev2(codec) \
2179 ((codec)->vendor_id == 0x11d41988 && \
2180 (codec)->revision_id == AD1988A_REV2)
2186 static const hda_nid_t ad1988_6stack_dac_nids
[4] = {
2187 0x04, 0x06, 0x05, 0x0a
2190 static const hda_nid_t ad1988_3stack_dac_nids
[3] = {
2194 /* for AD1988A revision-2, DAC2-4 are swapped */
2195 static const hda_nid_t ad1988_6stack_dac_nids_rev2
[4] = {
2196 0x04, 0x05, 0x0a, 0x06
2199 static const hda_nid_t ad1988_alt_dac_nid
[1] = {
2203 static const hda_nid_t ad1988_3stack_dac_nids_rev2
[3] = {
2207 static const hda_nid_t ad1988_adc_nids
[3] = {
2211 static const hda_nid_t ad1988_capsrc_nids
[3] = {
2215 #define AD1988_SPDIF_OUT 0x02
2216 #define AD1988_SPDIF_OUT_HDMI 0x0b
2217 #define AD1988_SPDIF_IN 0x07
2219 static const hda_nid_t ad1989b_slave_dig_outs
[] = {
2220 AD1988_SPDIF_OUT
, AD1988_SPDIF_OUT_HDMI
, 0
2223 static const struct hda_input_mux ad1988_6stack_capture_source
= {
2226 { "Front Mic", 0x1 }, /* port-B */
2227 { "Line", 0x2 }, /* port-C */
2228 { "Mic", 0x4 }, /* port-E */
2234 static const struct hda_input_mux ad1988_laptop_capture_source
= {
2237 { "Mic/Line", 0x1 }, /* port-B */
2245 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
2246 struct snd_ctl_elem_info
*uinfo
)
2248 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2249 struct ad198x_spec
*spec
= codec
->spec
;
2250 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
2251 spec
->num_channel_mode
);
2254 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
2255 struct snd_ctl_elem_value
*ucontrol
)
2257 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2258 struct ad198x_spec
*spec
= codec
->spec
;
2259 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
2260 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
2263 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
2264 struct snd_ctl_elem_value
*ucontrol
)
2266 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2267 struct ad198x_spec
*spec
= codec
->spec
;
2268 int err
= snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
2269 spec
->num_channel_mode
,
2270 &spec
->multiout
.max_channels
);
2271 if (err
>= 0 && spec
->need_dac_fix
)
2272 spec
->multiout
.num_dacs
= spec
->multiout
.max_channels
/ 2;
2276 static const struct snd_kcontrol_new ad1988_hp_mixers
[] = {
2278 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2279 .name
= "Independent HP",
2280 .info
= ad1988_independent_hp_info
,
2281 .get
= ad1988_independent_hp_get
,
2282 .put
= ad1988_independent_hp_put
,
2288 static const struct snd_kcontrol_new ad1988_6stack_mixers1
[] = {
2289 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2290 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2291 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2292 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2293 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2297 static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2
[] = {
2298 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2299 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
2300 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2301 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT
),
2302 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2306 static const struct snd_kcontrol_new ad1988_6stack_mixers2
[] = {
2307 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
2308 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2309 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT
),
2310 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT
),
2311 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT
),
2312 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT
),
2313 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2314 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2316 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2317 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2318 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2319 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2320 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2321 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2322 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2323 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2325 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2326 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2328 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2329 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
2334 static const struct snd_kcontrol_new ad1988_3stack_mixers1
[] = {
2335 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2336 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2337 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2338 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2342 static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2
[] = {
2343 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2344 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2345 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT
),
2346 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT
),
2350 static const struct snd_kcontrol_new ad1988_3stack_mixers2
[] = {
2351 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
2352 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2353 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT
),
2354 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT
),
2355 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT
),
2356 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2357 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2359 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2360 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2361 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2362 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2363 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2364 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2365 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2366 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2368 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2369 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2371 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2372 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
2374 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2375 .name
= "Channel Mode",
2376 .info
= ad198x_ch_mode_info
,
2377 .get
= ad198x_ch_mode_get
,
2378 .put
= ad198x_ch_mode_put
,
2385 static const struct snd_kcontrol_new ad1988_laptop_mixers
[] = {
2386 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
2387 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2388 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT
),
2389 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2391 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2392 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2393 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2394 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2395 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2396 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2398 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2399 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2401 HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
2404 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2405 .name
= "External Amplifier",
2406 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x12,
2407 .info
= ad198x_eapd_info
,
2408 .get
= ad198x_eapd_get
,
2409 .put
= ad198x_eapd_put
,
2410 .private_value
= 0x12, /* port-D */
2417 static const struct snd_kcontrol_new ad1988_capture_mixers
[] = {
2418 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
2419 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
2420 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
2421 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
2422 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT
),
2423 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT
),
2425 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2426 /* The multiple "Capture Source" controls confuse alsamixer
2427 * So call somewhat different..
2429 /* .name = "Capture Source", */
2430 .name
= "Input Source",
2432 .info
= ad198x_mux_enum_info
,
2433 .get
= ad198x_mux_enum_get
,
2434 .put
= ad198x_mux_enum_put
,
2439 static int ad1988_spdif_playback_source_info(struct snd_kcontrol
*kcontrol
,
2440 struct snd_ctl_elem_info
*uinfo
)
2442 static const char * const texts
[] = {
2443 "PCM", "ADC1", "ADC2", "ADC3"
2445 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
2447 uinfo
->value
.enumerated
.items
= 4;
2448 if (uinfo
->value
.enumerated
.item
>= 4)
2449 uinfo
->value
.enumerated
.item
= 3;
2450 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
2454 static int ad1988_spdif_playback_source_get(struct snd_kcontrol
*kcontrol
,
2455 struct snd_ctl_elem_value
*ucontrol
)
2457 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2460 sel
= snd_hda_codec_read(codec
, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE
,
2463 ucontrol
->value
.enumerated
.item
[0] = 0;
2465 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2466 AC_VERB_GET_CONNECT_SEL
, 0);
2471 ucontrol
->value
.enumerated
.item
[0] = sel
;
2476 static int ad1988_spdif_playback_source_put(struct snd_kcontrol
*kcontrol
,
2477 struct snd_ctl_elem_value
*ucontrol
)
2479 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2480 unsigned int val
, sel
;
2483 val
= ucontrol
->value
.enumerated
.item
[0];
2487 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2488 AC_VERB_GET_AMP_GAIN_MUTE
,
2490 change
= sel
& 0x80;
2492 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2493 AC_VERB_SET_AMP_GAIN_MUTE
,
2495 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2496 AC_VERB_SET_AMP_GAIN_MUTE
,
2500 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2501 AC_VERB_GET_AMP_GAIN_MUTE
,
2502 AC_AMP_GET_INPUT
| 0x01);
2503 change
= sel
& 0x80;
2505 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2506 AC_VERB_SET_AMP_GAIN_MUTE
,
2508 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2509 AC_VERB_SET_AMP_GAIN_MUTE
,
2512 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2513 AC_VERB_GET_CONNECT_SEL
, 0) + 1;
2514 change
|= sel
!= val
;
2516 snd_hda_codec_write_cache(codec
, 0x0b, 0,
2517 AC_VERB_SET_CONNECT_SEL
,
2523 static const struct snd_kcontrol_new ad1988_spdif_out_mixers
[] = {
2524 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2526 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2527 .name
= "IEC958 Playback Source",
2528 .subdevice
= HDA_SUBDEV_NID_FLAG
| 0x1b,
2529 .info
= ad1988_spdif_playback_source_info
,
2530 .get
= ad1988_spdif_playback_source_get
,
2531 .put
= ad1988_spdif_playback_source_put
,
2536 static const struct snd_kcontrol_new ad1988_spdif_in_mixers
[] = {
2537 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT
),
2541 static const struct snd_kcontrol_new ad1989_spdif_out_mixers
[] = {
2542 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2543 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
2548 * initialization verbs
2552 * for 6-stack (+dig)
2554 static const struct hda_verb ad1988_6stack_init_verbs
[] = {
2555 /* Front, Surround, CLFE, side DAC; unmute as default */
2556 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2557 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2558 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2559 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2560 /* Port-A front headphon path */
2561 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* DAC0:03h */
2562 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2563 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2564 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2565 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2566 /* Port-D line-out path */
2567 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2568 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2569 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2570 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2571 /* Port-F surround path */
2572 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2573 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2574 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2575 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2576 /* Port-G CLFE path */
2577 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2578 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2579 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2580 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2581 /* Port-H side path */
2582 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2583 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2584 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2585 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2587 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2588 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2589 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2590 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2591 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2592 /* Port-B front mic-in path */
2593 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2594 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2595 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2596 /* Port-C line-in path */
2597 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2598 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2599 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2600 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2601 /* Port-E mic-in path */
2602 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2603 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2604 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2605 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2606 /* Analog CD Input */
2607 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2608 /* Analog Mix output amp */
2609 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2614 static const struct hda_verb ad1988_6stack_fp_init_verbs
[] = {
2615 /* Headphone; unmute as default */
2616 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2617 /* Port-A front headphon path */
2618 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* DAC0:03h */
2619 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2620 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2621 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2622 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2627 static const struct hda_verb ad1988_capture_init_verbs
[] = {
2628 /* mute analog mix */
2629 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2630 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2631 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2632 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2633 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2635 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2636 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2637 /* select ADCs - front-mic */
2638 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2639 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2640 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2645 static const struct hda_verb ad1988_spdif_init_verbs
[] = {
2647 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
2648 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* ADC1 */
2649 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2650 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2652 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2657 static const struct hda_verb ad1988_spdif_in_init_verbs
[] = {
2658 /* unmute SPDIF input pin */
2659 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2663 /* AD1989 has no ADC -> SPDIF route */
2664 static const struct hda_verb ad1989_spdif_init_verbs
[] = {
2665 /* SPDIF-1 out pin */
2666 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2667 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2668 /* SPDIF-2/HDMI out pin */
2669 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2670 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2675 * verbs for 3stack (+dig)
2677 static const struct hda_verb ad1988_3stack_ch2_init
[] = {
2678 /* set port-C to line-in */
2679 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2680 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2681 /* set port-E to mic-in */
2682 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2683 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2687 static const struct hda_verb ad1988_3stack_ch6_init
[] = {
2688 /* set port-C to surround out */
2689 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2690 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2691 /* set port-E to CLFE out */
2692 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2693 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2697 static const struct hda_channel_mode ad1988_3stack_modes
[2] = {
2698 { 2, ad1988_3stack_ch2_init
},
2699 { 6, ad1988_3stack_ch6_init
},
2702 static const struct hda_verb ad1988_3stack_init_verbs
[] = {
2703 /* Front, Surround, CLFE, side DAC; unmute as default */
2704 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2705 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2706 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2707 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2708 /* Port-A front headphon path */
2709 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* DAC0:03h */
2710 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2711 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2712 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2713 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2714 /* Port-D line-out path */
2715 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2716 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2717 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2718 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2720 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2721 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2722 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2723 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2724 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2725 /* Port-B front mic-in path */
2726 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2727 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2728 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2729 /* Port-C line-in/surround path - 6ch mode as default */
2730 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2731 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2732 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2733 {0x31, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* output sel: DAC 0x05 */
2734 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2735 /* Port-E mic-in/CLFE path - 6ch mode as default */
2736 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2737 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2738 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2739 {0x32, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* output sel: DAC 0x0a */
2740 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2741 /* mute analog mix */
2742 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2743 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2744 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2745 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2746 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2747 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2748 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2749 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2750 /* select ADCs - front-mic */
2751 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2752 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2753 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2754 /* Analog Mix output amp */
2755 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2760 * verbs for laptop mode (+dig)
2762 static const struct hda_verb ad1988_laptop_hp_on
[] = {
2763 /* unmute port-A and mute port-D */
2764 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2765 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2768 static const struct hda_verb ad1988_laptop_hp_off
[] = {
2769 /* mute port-A and unmute port-D */
2770 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2771 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2775 #define AD1988_HP_EVENT 0x01
2777 static const struct hda_verb ad1988_laptop_init_verbs
[] = {
2778 /* Front, Surround, CLFE, side DAC; unmute as default */
2779 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2780 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2781 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2782 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2783 /* Port-A front headphon path */
2784 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* DAC0:03h */
2785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2786 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2787 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2788 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2789 /* unsolicited event for pin-sense */
2790 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1988_HP_EVENT
},
2791 /* Port-D line-out path + EAPD */
2792 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2793 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2794 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2795 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2796 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x00}, /* EAPD-off */
2798 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2799 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2800 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2801 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2802 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2803 /* Port-B mic-in path */
2804 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2805 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2806 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2807 /* Port-C docking station - try to output */
2808 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2809 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2810 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2811 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2812 /* mute analog mix */
2813 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2814 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2815 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2816 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2817 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2818 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2819 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2820 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2821 /* select ADCs - mic */
2822 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2823 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2824 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2825 /* Analog Mix output amp */
2826 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2830 static void ad1988_laptop_unsol_event(struct hda_codec
*codec
, unsigned int res
)
2832 if ((res
>> 26) != AD1988_HP_EVENT
)
2834 if (snd_hda_jack_detect(codec
, 0x11))
2835 snd_hda_sequence_write(codec
, ad1988_laptop_hp_on
);
2837 snd_hda_sequence_write(codec
, ad1988_laptop_hp_off
);
2840 #ifdef CONFIG_SND_HDA_POWER_SAVE
2841 static const struct hda_amp_list ad1988_loopbacks
[] = {
2842 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
2843 { 0x20, HDA_INPUT
, 1 }, /* Line */
2844 { 0x20, HDA_INPUT
, 4 }, /* Mic */
2845 { 0x20, HDA_INPUT
, 6 }, /* CD */
2851 * Automatic parse of I/O pins from the BIOS configuration
2859 static const struct snd_kcontrol_new ad1988_control_templates
[] = {
2860 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
2861 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
2862 HDA_BIND_MUTE(NULL
, 0, 0, 0),
2865 /* add dynamic controls */
2866 static int add_control(struct ad198x_spec
*spec
, int type
, const char *name
,
2869 struct snd_kcontrol_new
*knew
;
2871 snd_array_init(&spec
->kctls
, sizeof(*knew
), 32);
2872 knew
= snd_array_new(&spec
->kctls
);
2875 *knew
= ad1988_control_templates
[type
];
2876 knew
->name
= kstrdup(name
, GFP_KERNEL
);
2879 if (get_amp_nid_(val
))
2880 knew
->subdevice
= HDA_SUBDEV_AMP_FLAG
;
2881 knew
->private_value
= val
;
2885 #define AD1988_PIN_CD_NID 0x18
2886 #define AD1988_PIN_BEEP_NID 0x10
2888 static const hda_nid_t ad1988_mixer_nids
[8] = {
2889 /* A B C D E F G H */
2890 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2893 static inline hda_nid_t
ad1988_idx_to_dac(struct hda_codec
*codec
, int idx
)
2895 static const hda_nid_t idx_to_dac
[8] = {
2896 /* A B C D E F G H */
2897 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2899 static const hda_nid_t idx_to_dac_rev2
[8] = {
2900 /* A B C D E F G H */
2901 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2904 return idx_to_dac_rev2
[idx
];
2906 return idx_to_dac
[idx
];
2909 static const hda_nid_t ad1988_boost_nids
[8] = {
2910 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2913 static int ad1988_pin_idx(hda_nid_t nid
)
2915 static const hda_nid_t ad1988_io_pins
[8] = {
2916 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2919 for (i
= 0; i
< ARRAY_SIZE(ad1988_io_pins
); i
++)
2920 if (ad1988_io_pins
[i
] == nid
)
2922 return 0; /* should be -1 */
2925 static int ad1988_pin_to_loopback_idx(hda_nid_t nid
)
2927 static const int loopback_idx
[8] = {
2928 2, 0, 1, 3, 4, 5, 1, 4
2931 case AD1988_PIN_CD_NID
:
2934 return loopback_idx
[ad1988_pin_idx(nid
)];
2938 static int ad1988_pin_to_adc_idx(hda_nid_t nid
)
2940 static const int adc_idx
[8] = {
2941 0, 1, 2, 8, 4, 3, 6, 7
2944 case AD1988_PIN_CD_NID
:
2947 return adc_idx
[ad1988_pin_idx(nid
)];
2951 /* fill in the dac_nids table from the parsed pin configuration */
2952 static int ad1988_auto_fill_dac_nids(struct hda_codec
*codec
,
2953 const struct auto_pin_cfg
*cfg
)
2955 struct ad198x_spec
*spec
= codec
->spec
;
2958 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2960 /* check the pins hardwired to audio widget */
2961 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2962 idx
= ad1988_pin_idx(cfg
->line_out_pins
[i
]);
2963 spec
->private_dac_nids
[i
] = ad1988_idx_to_dac(codec
, idx
);
2965 spec
->multiout
.num_dacs
= cfg
->line_outs
;
2969 /* add playback controls from the parsed DAC table */
2970 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec
*spec
,
2971 const struct auto_pin_cfg
*cfg
)
2974 static const char * const chname
[4] = {
2975 "Front", "Surround", NULL
/*CLFE*/, "Side"
2980 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2981 hda_nid_t dac
= spec
->multiout
.dac_nids
[i
];
2984 nid
= ad1988_mixer_nids
[ad1988_pin_idx(cfg
->line_out_pins
[i
])];
2987 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2988 "Center Playback Volume",
2989 HDA_COMPOSE_AMP_VAL(dac
, 1, 0, HDA_OUTPUT
));
2992 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2993 "LFE Playback Volume",
2994 HDA_COMPOSE_AMP_VAL(dac
, 2, 0, HDA_OUTPUT
));
2997 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
2998 "Center Playback Switch",
2999 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
));
3002 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
3003 "LFE Playback Switch",
3004 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
));
3008 sprintf(name
, "%s Playback Volume", chname
[i
]);
3009 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
3010 HDA_COMPOSE_AMP_VAL(dac
, 3, 0, HDA_OUTPUT
));
3013 sprintf(name
, "%s Playback Switch", chname
[i
]);
3014 err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
3015 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
));
3023 /* add playback controls for speaker and HP outputs */
3024 static int ad1988_auto_create_extra_out(struct hda_codec
*codec
, hda_nid_t pin
,
3027 struct ad198x_spec
*spec
= codec
->spec
;
3035 idx
= ad1988_pin_idx(pin
);
3036 nid
= ad1988_idx_to_dac(codec
, idx
);
3037 /* check whether the corresponding DAC was already taken */
3038 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
3039 hda_nid_t pin
= spec
->autocfg
.line_out_pins
[i
];
3040 hda_nid_t dac
= ad1988_idx_to_dac(codec
, ad1988_pin_idx(pin
));
3044 if (i
>= spec
->autocfg
.line_outs
) {
3045 /* specify the DAC as the extra output */
3046 if (!spec
->multiout
.hp_nid
)
3047 spec
->multiout
.hp_nid
= nid
;
3049 spec
->multiout
.extra_out_nid
[0] = nid
;
3050 /* control HP volume/switch on the output mixer amp */
3051 sprintf(name
, "%s Playback Volume", pfx
);
3052 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
3053 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
3057 nid
= ad1988_mixer_nids
[idx
];
3058 sprintf(name
, "%s Playback Switch", pfx
);
3059 if ((err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
3060 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
3065 /* create input playback/capture controls for the given pin */
3066 static int new_analog_input(struct ad198x_spec
*spec
, hda_nid_t pin
,
3067 const char *ctlname
, int ctlidx
, int boost
)
3072 sprintf(name
, "%s Playback Volume", ctlname
);
3073 idx
= ad1988_pin_to_loopback_idx(pin
);
3074 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
3075 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
3077 sprintf(name
, "%s Playback Switch", ctlname
);
3078 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
, name
,
3079 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
3083 idx
= ad1988_pin_idx(pin
);
3084 bnid
= ad1988_boost_nids
[idx
];
3086 sprintf(name
, "%s Boost Volume", ctlname
);
3087 return add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
3088 HDA_COMPOSE_AMP_VAL(bnid
, 3, idx
, HDA_OUTPUT
));
3095 /* create playback/capture controls for input pins */
3096 static int ad1988_auto_create_analog_input_ctls(struct hda_codec
*codec
,
3097 const struct auto_pin_cfg
*cfg
)
3099 struct ad198x_spec
*spec
= codec
->spec
;
3100 struct hda_input_mux
*imux
= &spec
->private_imux
;
3101 int i
, err
, type
, type_idx
;
3103 for (i
= 0; i
< cfg
->num_inputs
; i
++) {
3105 type
= cfg
->inputs
[i
].type
;
3106 label
= hda_get_autocfg_input_label(codec
, cfg
, i
);
3107 snd_hda_add_imux_item(imux
, label
,
3108 ad1988_pin_to_adc_idx(cfg
->inputs
[i
].pin
),
3110 err
= new_analog_input(spec
, cfg
->inputs
[i
].pin
,
3112 type
== AUTO_PIN_MIC
);
3116 snd_hda_add_imux_item(imux
, "Mix", 9, NULL
);
3118 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
3119 "Analog Mix Playback Volume",
3120 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
3122 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
,
3123 "Analog Mix Playback Switch",
3124 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
3130 static void ad1988_auto_set_output_and_unmute(struct hda_codec
*codec
,
3131 hda_nid_t nid
, int pin_type
,
3135 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
3136 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
3138 case 0x11: /* port-A - DAC 03 */
3139 snd_hda_codec_write(codec
, 0x37, 0, AC_VERB_SET_CONNECT_SEL
, 0x00);
3141 case 0x14: /* port-B - DAC 06 */
3142 snd_hda_codec_write(codec
, 0x30, 0, AC_VERB_SET_CONNECT_SEL
, 0x02);
3144 case 0x15: /* port-C - DAC 05 */
3145 snd_hda_codec_write(codec
, 0x31, 0, AC_VERB_SET_CONNECT_SEL
, 0x00);
3147 case 0x17: /* port-E - DAC 0a */
3148 snd_hda_codec_write(codec
, 0x32, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
3150 case 0x13: /* mono - DAC 04 */
3151 snd_hda_codec_write(codec
, 0x36, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
3156 static void ad1988_auto_init_multi_out(struct hda_codec
*codec
)
3158 struct ad198x_spec
*spec
= codec
->spec
;
3161 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
3162 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
3163 ad1988_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
3167 static void ad1988_auto_init_extra_out(struct hda_codec
*codec
)
3169 struct ad198x_spec
*spec
= codec
->spec
;
3172 pin
= spec
->autocfg
.speaker_pins
[0];
3173 if (pin
) /* connect to front */
3174 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
3175 pin
= spec
->autocfg
.hp_pins
[0];
3176 if (pin
) /* connect to front */
3177 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
3180 static void ad1988_auto_init_analog_input(struct hda_codec
*codec
)
3182 struct ad198x_spec
*spec
= codec
->spec
;
3183 const struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
3186 for (i
= 0; i
< cfg
->num_inputs
; i
++) {
3187 hda_nid_t nid
= cfg
->inputs
[i
].pin
;
3188 int type
= cfg
->inputs
[i
].type
;
3190 case 0x15: /* port-C */
3191 snd_hda_codec_write(codec
, 0x33, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
3193 case 0x17: /* port-E */
3194 snd_hda_codec_write(codec
, 0x34, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
3197 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
3198 type
== AUTO_PIN_MIC
? PIN_VREF80
: PIN_IN
);
3199 if (nid
!= AD1988_PIN_CD_NID
)
3200 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3202 idx
= ad1988_pin_idx(nid
);
3203 if (ad1988_boost_nids
[idx
])
3204 snd_hda_codec_write(codec
, ad1988_boost_nids
[idx
], 0,
3205 AC_VERB_SET_AMP_GAIN_MUTE
,
3210 /* parse the BIOS configuration and set up the alc_spec */
3211 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3212 static int ad1988_parse_auto_config(struct hda_codec
*codec
)
3214 struct ad198x_spec
*spec
= codec
->spec
;
3217 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
3219 if ((err
= ad1988_auto_fill_dac_nids(codec
, &spec
->autocfg
)) < 0)
3221 if (! spec
->autocfg
.line_outs
)
3222 return 0; /* can't find valid BIOS pin config */
3223 if ((err
= ad1988_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
3224 (err
= ad1988_auto_create_extra_out(codec
,
3225 spec
->autocfg
.speaker_pins
[0],
3227 (err
= ad1988_auto_create_extra_out(codec
, spec
->autocfg
.hp_pins
[0],
3228 "Headphone")) < 0 ||
3229 (err
= ad1988_auto_create_analog_input_ctls(codec
, &spec
->autocfg
)) < 0)
3232 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
3234 if (spec
->autocfg
.dig_outs
)
3235 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3236 if (spec
->autocfg
.dig_in_pin
)
3237 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
3239 if (spec
->kctls
.list
)
3240 spec
->mixers
[spec
->num_mixers
++] = spec
->kctls
.list
;
3242 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_6stack_init_verbs
;
3244 spec
->input_mux
= &spec
->private_imux
;
3249 /* init callback for auto-configuration model -- overriding the default init */
3250 static int ad1988_auto_init(struct hda_codec
*codec
)
3253 ad1988_auto_init_multi_out(codec
);
3254 ad1988_auto_init_extra_out(codec
);
3255 ad1988_auto_init_analog_input(codec
);
3262 static const char * const ad1988_models
[AD1988_MODEL_LAST
] = {
3263 [AD1988_6STACK
] = "6stack",
3264 [AD1988_6STACK_DIG
] = "6stack-dig",
3265 [AD1988_3STACK
] = "3stack",
3266 [AD1988_3STACK_DIG
] = "3stack-dig",
3267 [AD1988_LAPTOP
] = "laptop",
3268 [AD1988_LAPTOP_DIG
] = "laptop-dig",
3269 [AD1988_AUTO
] = "auto",
3272 static const struct snd_pci_quirk ad1988_cfg_tbl
[] = {
3273 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG
),
3274 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG
),
3275 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG
),
3276 SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG
),
3277 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG
),
3281 static int patch_ad1988(struct hda_codec
*codec
)
3283 struct ad198x_spec
*spec
;
3284 int err
, board_config
;
3286 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3293 snd_printk(KERN_INFO
"patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3295 board_config
= snd_hda_check_board_config(codec
, AD1988_MODEL_LAST
,
3296 ad1988_models
, ad1988_cfg_tbl
);
3297 if (board_config
< 0) {
3298 printk(KERN_INFO
"hda_codec: %s: BIOS auto-probing.\n",
3300 board_config
= AD1988_AUTO
;
3303 if (board_config
== AD1988_AUTO
) {
3304 /* automatic parse from the BIOS config */
3305 err
= ad1988_parse_auto_config(codec
);
3310 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3311 board_config
= AD1988_6STACK
;
3315 err
= snd_hda_attach_beep_device(codec
, 0x10);
3320 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3322 if (!spec
->multiout
.hp_nid
)
3323 spec
->multiout
.hp_nid
= ad1988_alt_dac_nid
[0];
3324 switch (board_config
) {
3326 case AD1988_6STACK_DIG
:
3327 spec
->multiout
.max_channels
= 8;
3328 spec
->multiout
.num_dacs
= 4;
3330 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids_rev2
;
3332 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids
;
3333 spec
->input_mux
= &ad1988_6stack_capture_source
;
3334 spec
->num_mixers
= 2;
3336 spec
->mixers
[0] = ad1988_6stack_mixers1_rev2
;
3338 spec
->mixers
[0] = ad1988_6stack_mixers1
;
3339 spec
->mixers
[1] = ad1988_6stack_mixers2
;
3340 spec
->num_init_verbs
= 1;
3341 spec
->init_verbs
[0] = ad1988_6stack_init_verbs
;
3342 if (board_config
== AD1988_6STACK_DIG
) {
3343 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3344 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
3348 case AD1988_3STACK_DIG
:
3349 spec
->multiout
.max_channels
= 6;
3350 spec
->multiout
.num_dacs
= 3;
3352 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids_rev2
;
3354 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3355 spec
->input_mux
= &ad1988_6stack_capture_source
;
3356 spec
->channel_mode
= ad1988_3stack_modes
;
3357 spec
->num_channel_mode
= ARRAY_SIZE(ad1988_3stack_modes
);
3358 spec
->num_mixers
= 2;
3360 spec
->mixers
[0] = ad1988_3stack_mixers1_rev2
;
3362 spec
->mixers
[0] = ad1988_3stack_mixers1
;
3363 spec
->mixers
[1] = ad1988_3stack_mixers2
;
3364 spec
->num_init_verbs
= 1;
3365 spec
->init_verbs
[0] = ad1988_3stack_init_verbs
;
3366 if (board_config
== AD1988_3STACK_DIG
)
3367 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3370 case AD1988_LAPTOP_DIG
:
3371 spec
->multiout
.max_channels
= 2;
3372 spec
->multiout
.num_dacs
= 1;
3373 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3374 spec
->input_mux
= &ad1988_laptop_capture_source
;
3375 spec
->num_mixers
= 1;
3376 spec
->mixers
[0] = ad1988_laptop_mixers
;
3377 spec
->inv_eapd
= 1; /* inverted EAPD */
3378 spec
->num_init_verbs
= 1;
3379 spec
->init_verbs
[0] = ad1988_laptop_init_verbs
;
3380 if (board_config
== AD1988_LAPTOP_DIG
)
3381 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3385 if (spec
->autocfg
.hp_pins
[0]) {
3386 spec
->mixers
[spec
->num_mixers
++] = ad1988_hp_mixers
;
3387 spec
->slave_vols
= ad1988_6stack_fp_slave_vols
;
3388 spec
->slave_sws
= ad1988_6stack_fp_slave_sws
;
3389 spec
->alt_dac_nid
= ad1988_alt_dac_nid
;
3390 spec
->stream_analog_alt_playback
=
3391 &ad198x_pcm_analog_alt_playback
;
3394 spec
->num_adc_nids
= ARRAY_SIZE(ad1988_adc_nids
);
3395 spec
->adc_nids
= ad1988_adc_nids
;
3396 spec
->capsrc_nids
= ad1988_capsrc_nids
;
3397 spec
->mixers
[spec
->num_mixers
++] = ad1988_capture_mixers
;
3398 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_capture_init_verbs
;
3399 if (spec
->multiout
.dig_out_nid
) {
3400 if (codec
->vendor_id
>= 0x11d4989a) {
3401 spec
->mixers
[spec
->num_mixers
++] =
3402 ad1989_spdif_out_mixers
;
3403 spec
->init_verbs
[spec
->num_init_verbs
++] =
3404 ad1989_spdif_init_verbs
;
3405 codec
->slave_dig_outs
= ad1989b_slave_dig_outs
;
3407 spec
->mixers
[spec
->num_mixers
++] =
3408 ad1988_spdif_out_mixers
;
3409 spec
->init_verbs
[spec
->num_init_verbs
++] =
3410 ad1988_spdif_init_verbs
;
3413 if (spec
->dig_in_nid
&& codec
->vendor_id
< 0x11d4989a) {
3414 spec
->mixers
[spec
->num_mixers
++] = ad1988_spdif_in_mixers
;
3415 spec
->init_verbs
[spec
->num_init_verbs
++] =
3416 ad1988_spdif_in_init_verbs
;
3419 codec
->patch_ops
= ad198x_patch_ops
;
3420 switch (board_config
) {
3422 codec
->patch_ops
.init
= ad1988_auto_init
;
3425 case AD1988_LAPTOP_DIG
:
3426 codec
->patch_ops
.unsol_event
= ad1988_laptop_unsol_event
;
3429 #ifdef CONFIG_SND_HDA_POWER_SAVE
3430 spec
->loopback
.amplist
= ad1988_loopbacks
;
3432 spec
->vmaster_nid
= 0x04;
3434 codec
->no_trigger_sense
= 1;
3435 codec
->no_sticky_stream
= 1;
3444 * port-B - front line/mic-in
3445 * port-E - aux in/out
3446 * port-F - aux in/out
3447 * port-C - rear line/mic-in
3448 * port-D - rear line/hp-out
3449 * port-A - front line/hp-out
3451 * AD1984 = AD1884 + two digital mic-ins
3454 * For simplicity, we share the single DAC for both HP and line-outs
3455 * right now. The inidividual playbacks could be easily implemented,
3456 * but no build-up framework is given, so far.
3459 static const hda_nid_t ad1884_dac_nids
[1] = {
3463 static const hda_nid_t ad1884_adc_nids
[2] = {
3467 static const hda_nid_t ad1884_capsrc_nids
[2] = {
3471 #define AD1884_SPDIF_OUT 0x02
3473 static const struct hda_input_mux ad1884_capture_source
= {
3476 { "Front Mic", 0x0 },
3483 static const struct snd_kcontrol_new ad1884_base_mixers
[] = {
3484 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3485 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3486 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3487 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3488 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3489 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3490 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3491 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3492 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3493 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3494 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3495 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3496 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
3497 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3498 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3499 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3500 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3501 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3503 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3504 /* The multiple "Capture Source" controls confuse alsamixer
3505 * So call somewhat different..
3507 /* .name = "Capture Source", */
3508 .name
= "Input Source",
3510 .info
= ad198x_mux_enum_info
,
3511 .get
= ad198x_mux_enum_get
,
3512 .put
= ad198x_mux_enum_put
,
3514 /* SPDIF controls */
3515 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3517 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3518 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3519 /* identical with ad1983 */
3520 .info
= ad1983_spdif_route_info
,
3521 .get
= ad1983_spdif_route_get
,
3522 .put
= ad1983_spdif_route_put
,
3527 static const struct snd_kcontrol_new ad1984_dmic_mixers
[] = {
3528 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT
),
3529 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT
),
3530 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3532 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3538 * initialization verbs
3540 static const struct hda_verb ad1884_init_verbs
[] = {
3541 /* DACs; mute as default */
3542 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3543 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3544 /* Port-A (HP) mixer */
3545 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3546 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3548 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3549 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3550 /* HP selector - select DAC2 */
3551 {0x22, AC_VERB_SET_CONNECT_SEL
, 0x1},
3552 /* Port-D (Line-out) mixer */
3553 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3554 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3556 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3557 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3558 /* Mono-out mixer */
3559 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3560 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3562 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3563 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3565 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
3566 /* Port-B (front mic) pin */
3567 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3568 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3569 /* Port-C (rear mic) pin */
3570 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3571 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3572 /* Analog mixer; mute as default */
3573 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3574 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3575 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3576 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3577 /* Analog Mix output amp */
3578 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
3579 /* SPDIF output selector */
3580 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
3581 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
3585 #ifdef CONFIG_SND_HDA_POWER_SAVE
3586 static const struct hda_amp_list ad1884_loopbacks
[] = {
3587 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
3588 { 0x20, HDA_INPUT
, 1 }, /* Mic */
3589 { 0x20, HDA_INPUT
, 2 }, /* CD */
3590 { 0x20, HDA_INPUT
, 4 }, /* Docking */
3595 static const char * const ad1884_slave_vols
[] = {
3596 "PCM Playback Volume",
3597 "Mic Playback Volume",
3598 "Mono Playback Volume",
3599 "Front Mic Playback Volume",
3600 "Mic Playback Volume",
3601 "CD Playback Volume",
3602 "Internal Mic Playback Volume",
3603 "Docking Mic Playback Volume",
3604 /* "Beep Playback Volume", */
3605 "IEC958 Playback Volume",
3609 static int patch_ad1884(struct hda_codec
*codec
)
3611 struct ad198x_spec
*spec
;
3614 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3620 err
= snd_hda_attach_beep_device(codec
, 0x10);
3625 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3627 spec
->multiout
.max_channels
= 2;
3628 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884_dac_nids
);
3629 spec
->multiout
.dac_nids
= ad1884_dac_nids
;
3630 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3631 spec
->num_adc_nids
= ARRAY_SIZE(ad1884_adc_nids
);
3632 spec
->adc_nids
= ad1884_adc_nids
;
3633 spec
->capsrc_nids
= ad1884_capsrc_nids
;
3634 spec
->input_mux
= &ad1884_capture_source
;
3635 spec
->num_mixers
= 1;
3636 spec
->mixers
[0] = ad1884_base_mixers
;
3637 spec
->num_init_verbs
= 1;
3638 spec
->init_verbs
[0] = ad1884_init_verbs
;
3639 spec
->spdif_route
= 0;
3640 #ifdef CONFIG_SND_HDA_POWER_SAVE
3641 spec
->loopback
.amplist
= ad1884_loopbacks
;
3643 spec
->vmaster_nid
= 0x04;
3644 /* we need to cover all playback volumes */
3645 spec
->slave_vols
= ad1884_slave_vols
;
3647 codec
->patch_ops
= ad198x_patch_ops
;
3649 codec
->no_trigger_sense
= 1;
3650 codec
->no_sticky_stream
= 1;
3656 * Lenovo Thinkpad T61/X61
3658 static const struct hda_input_mux ad1984_thinkpad_capture_source
= {
3662 { "Internal Mic", 0x1 },
3664 { "Docking-Station", 0x4 },
3670 * Dell Precision T3400
3672 static const struct hda_input_mux ad1984_dell_desktop_capture_source
= {
3675 { "Front Mic", 0x0 },
3682 static const struct snd_kcontrol_new ad1984_thinkpad_mixers
[] = {
3683 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3684 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3685 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3686 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3687 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3688 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3689 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3690 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3691 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT
),
3692 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT
),
3693 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3694 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3695 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3696 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
3697 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
3698 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3699 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3700 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3701 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3703 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3704 /* The multiple "Capture Source" controls confuse alsamixer
3705 * So call somewhat different..
3707 /* .name = "Capture Source", */
3708 .name
= "Input Source",
3710 .info
= ad198x_mux_enum_info
,
3711 .get
= ad198x_mux_enum_get
,
3712 .put
= ad198x_mux_enum_put
,
3714 /* SPDIF controls */
3715 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3717 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3718 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3719 /* identical with ad1983 */
3720 .info
= ad1983_spdif_route_info
,
3721 .get
= ad1983_spdif_route_get
,
3722 .put
= ad1983_spdif_route_put
,
3727 /* additional verbs */
3728 static const struct hda_verb ad1984_thinkpad_init_verbs
[] = {
3729 /* Port-E (docking station mic) pin */
3730 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3731 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3732 /* docking mic boost */
3733 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3734 /* Analog PC Beeper - allow firmware/ACPI beeps */
3735 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3) | 0x1a},
3736 /* Analog mixer - docking mic; mute as default */
3737 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3738 /* enable EAPD bit */
3739 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
3744 * Dell Precision T3400
3746 static const struct snd_kcontrol_new ad1984_dell_desktop_mixers
[] = {
3747 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3748 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3749 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3750 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3751 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3752 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3753 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3754 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT
),
3755 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT
),
3756 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT
),
3757 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3758 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3759 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3760 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3761 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3763 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3764 /* The multiple "Capture Source" controls confuse alsamixer
3765 * So call somewhat different..
3767 /* .name = "Capture Source", */
3768 .name
= "Input Source",
3770 .info
= ad198x_mux_enum_info
,
3771 .get
= ad198x_mux_enum_get
,
3772 .put
= ad198x_mux_enum_put
,
3777 /* Digial MIC ADC NID 0x05 + 0x06 */
3778 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream
*hinfo
,
3779 struct hda_codec
*codec
,
3780 unsigned int stream_tag
,
3781 unsigned int format
,
3782 struct snd_pcm_substream
*substream
)
3784 snd_hda_codec_setup_stream(codec
, 0x05 + substream
->number
,
3785 stream_tag
, 0, format
);
3789 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream
*hinfo
,
3790 struct hda_codec
*codec
,
3791 struct snd_pcm_substream
*substream
)
3793 snd_hda_codec_cleanup_stream(codec
, 0x05 + substream
->number
);
3797 static const struct hda_pcm_stream ad1984_pcm_dmic_capture
= {
3803 .prepare
= ad1984_pcm_dmic_prepare
,
3804 .cleanup
= ad1984_pcm_dmic_cleanup
3808 static int ad1984_build_pcms(struct hda_codec
*codec
)
3810 struct ad198x_spec
*spec
= codec
->spec
;
3811 struct hda_pcm
*info
;
3814 err
= ad198x_build_pcms(codec
);
3818 info
= spec
->pcm_rec
+ codec
->num_pcms
;
3820 info
->name
= "AD1984 Digital Mic";
3821 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad1984_pcm_dmic_capture
;
3829 AD1984_DELL_DESKTOP
,
3833 static const char * const ad1984_models
[AD1984_MODELS
] = {
3834 [AD1984_BASIC
] = "basic",
3835 [AD1984_THINKPAD
] = "thinkpad",
3836 [AD1984_DELL_DESKTOP
] = "dell_desktop",
3839 static const struct snd_pci_quirk ad1984_cfg_tbl
[] = {
3840 /* Lenovo Thinkpad T61/X61 */
3841 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD
),
3842 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP
),
3843 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP
),
3847 static int patch_ad1984(struct hda_codec
*codec
)
3849 struct ad198x_spec
*spec
;
3850 int board_config
, err
;
3852 err
= patch_ad1884(codec
);
3856 board_config
= snd_hda_check_board_config(codec
, AD1984_MODELS
,
3857 ad1984_models
, ad1984_cfg_tbl
);
3858 switch (board_config
) {
3860 /* additional digital mics */
3861 spec
->mixers
[spec
->num_mixers
++] = ad1984_dmic_mixers
;
3862 codec
->patch_ops
.build_pcms
= ad1984_build_pcms
;
3864 case AD1984_THINKPAD
:
3865 if (codec
->subsystem_id
== 0x17aa20fb) {
3866 /* Thinpad X300 does not have the ability to do SPDIF,
3867 or attach to docking station to use SPDIF */
3868 spec
->multiout
.dig_out_nid
= 0;
3870 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3871 spec
->input_mux
= &ad1984_thinkpad_capture_source
;
3872 spec
->mixers
[0] = ad1984_thinkpad_mixers
;
3873 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1984_thinkpad_init_verbs
;
3874 spec
->analog_beep
= 1;
3876 case AD1984_DELL_DESKTOP
:
3877 spec
->multiout
.dig_out_nid
= 0;
3878 spec
->input_mux
= &ad1984_dell_desktop_capture_source
;
3879 spec
->mixers
[0] = ad1984_dell_desktop_mixers
;
3887 * AD1883 / AD1884A / AD1984A / AD1984B
3889 * port-B (0x14) - front mic-in
3890 * port-E (0x1c) - rear mic-in
3891 * port-F (0x16) - CD / ext out
3892 * port-C (0x15) - rear line-in
3893 * port-D (0x12) - rear line-out
3894 * port-A (0x11) - front hp-out
3896 * AD1984A = AD1884A + digital-mic
3897 * AD1883 = equivalent with AD1984A
3898 * AD1984B = AD1984A + extra SPDIF-out
3901 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3904 static const hda_nid_t ad1884a_dac_nids
[1] = {
3908 #define ad1884a_adc_nids ad1884_adc_nids
3909 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3911 #define AD1884A_SPDIF_OUT 0x02
3913 static const struct hda_input_mux ad1884a_capture_source
= {
3916 { "Front Mic", 0x0 },
3924 static const struct snd_kcontrol_new ad1884a_base_mixers
[] = {
3925 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3926 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
3927 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3928 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3929 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3930 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3931 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3932 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3933 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3934 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3935 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
3936 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
3937 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3938 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3939 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3940 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3941 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
3942 HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT
),
3943 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
3944 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3945 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3946 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3947 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3949 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3950 /* The multiple "Capture Source" controls confuse alsamixer
3951 * So call somewhat different..
3953 /* .name = "Capture Source", */
3954 .name
= "Input Source",
3956 .info
= ad198x_mux_enum_info
,
3957 .get
= ad198x_mux_enum_get
,
3958 .put
= ad198x_mux_enum_put
,
3960 /* SPDIF controls */
3961 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3963 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3964 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3965 /* identical with ad1983 */
3966 .info
= ad1983_spdif_route_info
,
3967 .get
= ad1983_spdif_route_get
,
3968 .put
= ad1983_spdif_route_put
,
3974 * initialization verbs
3976 static const struct hda_verb ad1884a_init_verbs
[] = {
3977 /* DACs; unmute as default */
3978 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3979 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3980 /* Port-A (HP) mixer - route only from analog mixer */
3981 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3982 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3984 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3985 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3986 /* Port-D (Line-out) mixer - route only from analog mixer */
3987 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3988 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3990 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3991 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3992 /* Mono-out mixer - route only from analog mixer */
3993 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3994 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3996 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3997 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3998 /* Port-B (front mic) pin */
3999 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4000 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4001 /* Port-C (rear line-in) pin */
4002 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4003 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4004 /* Port-E (rear mic) pin */
4005 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4006 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4007 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* no boost */
4008 /* Port-F (CD) pin */
4009 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4010 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4011 /* Analog mixer; mute as default */
4012 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4013 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4014 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4015 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4016 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)}, /* aux */
4017 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4018 /* Analog Mix output amp */
4019 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4020 /* capture sources */
4021 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
4022 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4023 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4024 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4025 /* SPDIF output amp */
4026 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4030 #ifdef CONFIG_SND_HDA_POWER_SAVE
4031 static const struct hda_amp_list ad1884a_loopbacks
[] = {
4032 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
4033 { 0x20, HDA_INPUT
, 1 }, /* Mic */
4034 { 0x20, HDA_INPUT
, 2 }, /* CD */
4035 { 0x20, HDA_INPUT
, 4 }, /* Docking */
4043 * Port A: Headphone jack
4045 * Port C: Internal MIC
4046 * Port D: Dock Line Out (if enabled)
4047 * Port E: Dock Line In (if enabled)
4048 * Port F: Internal speakers
4051 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol
*kcontrol
,
4052 struct snd_ctl_elem_value
*ucontrol
)
4054 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
4055 int ret
= snd_hda_mixer_amp_switch_put(kcontrol
, ucontrol
);
4056 int mute
= (!ucontrol
->value
.integer
.value
[0] &&
4057 !ucontrol
->value
.integer
.value
[1]);
4058 /* toggle GPIO1 according to the mute state */
4059 snd_hda_codec_write_cache(codec
, 0x01, 0, AC_VERB_SET_GPIO_DATA
,
4064 static const struct snd_kcontrol_new ad1884a_laptop_mixers
[] = {
4065 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4067 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4068 .name
= "Master Playback Switch",
4069 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
4070 .info
= snd_hda_mixer_amp_switch_info
,
4071 .get
= snd_hda_mixer_amp_switch_get
,
4072 .put
= ad1884a_mobile_master_sw_put
,
4073 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
4075 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
4076 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4077 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4078 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4079 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4080 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
4081 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
4082 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
4083 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
4084 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
4085 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
4086 HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
4087 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4088 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4092 static const struct snd_kcontrol_new ad1884a_mobile_mixers
[] = {
4093 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4094 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4096 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4097 .name
= "Master Playback Switch",
4098 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
4099 .info
= snd_hda_mixer_amp_switch_info
,
4100 .get
= snd_hda_mixer_amp_switch_get
,
4101 .put
= ad1884a_mobile_master_sw_put
,
4102 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
4104 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4105 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4106 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT
),
4107 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT
),
4108 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4109 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4113 /* mute internal speaker if HP is plugged */
4114 static void ad1884a_hp_automute(struct hda_codec
*codec
)
4116 unsigned int present
;
4118 present
= snd_hda_jack_detect(codec
, 0x11);
4119 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
4120 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4121 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
4122 present
? 0x00 : 0x02);
4125 /* switch to external mic if plugged */
4126 static void ad1884a_hp_automic(struct hda_codec
*codec
)
4128 unsigned int present
;
4130 present
= snd_hda_jack_detect(codec
, 0x14);
4131 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
,
4135 #define AD1884A_HP_EVENT 0x37
4136 #define AD1884A_MIC_EVENT 0x36
4138 /* unsolicited event for HP jack sensing */
4139 static void ad1884a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
4141 switch (res
>> 26) {
4142 case AD1884A_HP_EVENT
:
4143 ad1884a_hp_automute(codec
);
4145 case AD1884A_MIC_EVENT
:
4146 ad1884a_hp_automic(codec
);
4151 /* initialize jack-sensing, too */
4152 static int ad1884a_hp_init(struct hda_codec
*codec
)
4155 ad1884a_hp_automute(codec
);
4156 ad1884a_hp_automic(codec
);
4160 /* mute internal speaker if HP or docking HP is plugged */
4161 static void ad1884a_laptop_automute(struct hda_codec
*codec
)
4163 unsigned int present
;
4165 present
= snd_hda_jack_detect(codec
, 0x11);
4167 present
= snd_hda_jack_detect(codec
, 0x12);
4168 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
4169 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4170 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
4171 present
? 0x00 : 0x02);
4174 /* switch to external mic if plugged */
4175 static void ad1884a_laptop_automic(struct hda_codec
*codec
)
4179 if (snd_hda_jack_detect(codec
, 0x14))
4181 else if (snd_hda_jack_detect(codec
, 0x1c))
4185 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
, idx
);
4188 /* unsolicited event for HP jack sensing */
4189 static void ad1884a_laptop_unsol_event(struct hda_codec
*codec
,
4192 switch (res
>> 26) {
4193 case AD1884A_HP_EVENT
:
4194 ad1884a_laptop_automute(codec
);
4196 case AD1884A_MIC_EVENT
:
4197 ad1884a_laptop_automic(codec
);
4202 /* initialize jack-sensing, too */
4203 static int ad1884a_laptop_init(struct hda_codec
*codec
)
4206 ad1884a_laptop_automute(codec
);
4207 ad1884a_laptop_automic(codec
);
4211 /* additional verbs for laptop model */
4212 static const struct hda_verb ad1884a_laptop_verbs
[] = {
4213 /* Port-A (HP) pin - always unmuted */
4214 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4215 /* Port-F (int speaker) mixer - route only from analog mixer */
4216 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4217 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4218 /* Port-F (int speaker) pin */
4219 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4220 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4221 /* required for compaq 6530s/6531s speaker output */
4222 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4223 /* Port-C pin - internal mic-in */
4224 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4225 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4226 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4227 /* Port-D (docking line-out) pin - default unmuted */
4228 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4230 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4231 /* unsolicited event for pin-sense */
4232 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4233 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4234 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4235 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4236 /* allow to touch GPIO1 (for mute control) */
4237 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4238 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4239 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4243 static const struct hda_verb ad1884a_mobile_verbs
[] = {
4244 /* DACs; unmute as default */
4245 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4246 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4247 /* Port-A (HP) mixer - route only from analog mixer */
4248 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4249 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4251 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4252 /* Port-A (HP) pin - always unmuted */
4253 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4254 /* Port-B (mic jack) pin */
4255 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4256 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4257 /* Port-C (int mic) pin */
4258 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4259 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4260 /* Port-F (int speaker) mixer - route only from analog mixer */
4261 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4262 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4264 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4265 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4266 /* Analog mixer; mute as default */
4267 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4268 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4269 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4270 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4271 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4272 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4273 /* Analog Mix output amp */
4274 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4275 /* capture sources */
4276 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4277 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4278 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4279 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4280 /* unsolicited event for pin-sense */
4281 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4282 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4283 /* allow to touch GPIO1 (for mute control) */
4284 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4285 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4286 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4295 * 0x17 - built-in mic
4298 static const struct hda_verb ad1984a_thinkpad_verbs
[] = {
4300 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4302 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4304 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
4305 /* unsolicited event for pin-sense */
4306 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4307 /* internal mic - dmic */
4308 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4309 /* set magic COEFs for dmic */
4310 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
4311 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
4315 static const struct snd_kcontrol_new ad1984a_thinkpad_mixers
[] = {
4316 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4317 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
4318 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4319 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4320 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4321 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4322 HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT
),
4323 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT
),
4324 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4325 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4327 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4328 .name
= "Capture Source",
4329 .info
= ad198x_mux_enum_info
,
4330 .get
= ad198x_mux_enum_get
,
4331 .put
= ad198x_mux_enum_put
,
4336 static const struct hda_input_mux ad1984a_thinkpad_capture_source
= {
4340 { "Internal Mic", 0x5 },
4345 /* mute internal speaker if HP is plugged */
4346 static void ad1984a_thinkpad_automute(struct hda_codec
*codec
)
4348 unsigned int present
;
4350 present
= snd_hda_jack_detect(codec
, 0x11);
4351 snd_hda_codec_amp_stereo(codec
, 0x12, HDA_OUTPUT
, 0,
4352 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4355 /* unsolicited event for HP jack sensing */
4356 static void ad1984a_thinkpad_unsol_event(struct hda_codec
*codec
,
4359 if ((res
>> 26) != AD1884A_HP_EVENT
)
4361 ad1984a_thinkpad_automute(codec
);
4364 /* initialize jack-sensing, too */
4365 static int ad1984a_thinkpad_init(struct hda_codec
*codec
)
4368 ad1984a_thinkpad_automute(codec
);
4374 * 0x12 - HP/line-out
4375 * 0x13 - speaker (mono)
4379 static const struct hda_verb ad1984a_precision_verbs
[] = {
4380 /* Unmute main output path */
4381 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4382 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
+ 0x1f}, /* 0dB */
4383 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4384 /* Analog mixer; mute as default */
4385 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4386 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4387 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4388 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4389 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4390 /* Select mic as input */
4391 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
4392 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
+ 0x27}, /* 0dB */
4393 /* Configure as mic */
4394 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4395 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
4397 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4399 {0x13, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
4400 /* unsolicited event for pin-sense */
4401 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4405 static const struct snd_kcontrol_new ad1984a_precision_mixers
[] = {
4406 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4407 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
4408 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4409 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4410 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
4411 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
4412 HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT
),
4413 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
4414 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
4415 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4416 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4421 /* mute internal speaker if HP is plugged */
4422 static void ad1984a_precision_automute(struct hda_codec
*codec
)
4424 unsigned int present
;
4426 present
= snd_hda_jack_detect(codec
, 0x12);
4427 snd_hda_codec_amp_stereo(codec
, 0x13, HDA_OUTPUT
, 0,
4428 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4432 /* unsolicited event for HP jack sensing */
4433 static void ad1984a_precision_unsol_event(struct hda_codec
*codec
,
4436 if ((res
>> 26) != AD1884A_HP_EVENT
)
4438 ad1984a_precision_automute(codec
);
4441 /* initialize jack-sensing, too */
4442 static int ad1984a_precision_init(struct hda_codec
*codec
)
4445 ad1984a_precision_automute(codec
);
4452 * port-A (0x11) - front hp-out
4453 * port-B (0x14) - unused
4454 * port-C (0x15) - unused
4455 * port-D (0x12) - rear line out
4456 * port-E (0x1c) - front mic-in
4457 * port-F (0x16) - Internal speakers
4458 * digital-mic (0x17) - Internal mic
4461 static const struct hda_verb ad1984a_touchsmart_verbs
[] = {
4462 /* DACs; unmute as default */
4463 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4464 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4465 /* Port-A (HP) mixer - route only from analog mixer */
4466 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4467 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4469 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4470 /* Port-A (HP) pin - always unmuted */
4471 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4472 /* Port-E (int speaker) mixer - route only from analog mixer */
4473 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, 0x03},
4475 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4476 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4477 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4478 /* Port-F (int speaker) mixer - route only from analog mixer */
4479 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4480 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4482 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4483 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4484 /* Analog mixer; mute as default */
4485 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4486 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4487 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4488 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4489 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4490 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4491 /* Analog Mix output amp */
4492 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4493 /* capture sources */
4494 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4495 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4496 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4497 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4498 /* unsolicited event for pin-sense */
4499 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4500 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4501 /* allow to touch GPIO1 (for mute control) */
4502 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4503 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4504 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4505 /* internal mic - dmic */
4506 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4507 /* set magic COEFs for dmic */
4508 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
4509 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
4513 static const struct snd_kcontrol_new ad1984a_touchsmart_mixers
[] = {
4514 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4515 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4517 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4518 .subdevice
= HDA_SUBDEV_AMP_FLAG
,
4519 .name
= "Master Playback Switch",
4520 .info
= snd_hda_mixer_amp_switch_info
,
4521 .get
= snd_hda_mixer_amp_switch_get
,
4522 .put
= ad1884a_mobile_master_sw_put
,
4523 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
4525 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4526 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4527 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4528 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4529 HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT
),
4530 HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT
),
4534 /* switch to external mic if plugged */
4535 static void ad1984a_touchsmart_automic(struct hda_codec
*codec
)
4537 if (snd_hda_jack_detect(codec
, 0x1c))
4538 snd_hda_codec_write(codec
, 0x0c, 0,
4539 AC_VERB_SET_CONNECT_SEL
, 0x4);
4541 snd_hda_codec_write(codec
, 0x0c, 0,
4542 AC_VERB_SET_CONNECT_SEL
, 0x5);
4546 /* unsolicited event for HP jack sensing */
4547 static void ad1984a_touchsmart_unsol_event(struct hda_codec
*codec
,
4550 switch (res
>> 26) {
4551 case AD1884A_HP_EVENT
:
4552 ad1884a_hp_automute(codec
);
4554 case AD1884A_MIC_EVENT
:
4555 ad1984a_touchsmart_automic(codec
);
4560 /* initialize jack-sensing, too */
4561 static int ad1984a_touchsmart_init(struct hda_codec
*codec
)
4564 ad1884a_hp_automute(codec
);
4565 ad1984a_touchsmart_automic(codec
);
4583 static const char * const ad1884a_models
[AD1884A_MODELS
] = {
4584 [AD1884A_DESKTOP
] = "desktop",
4585 [AD1884A_LAPTOP
] = "laptop",
4586 [AD1884A_MOBILE
] = "mobile",
4587 [AD1884A_THINKPAD
] = "thinkpad",
4588 [AD1984A_TOUCHSMART
] = "touchsmart",
4589 [AD1984A_PRECISION
] = "precision",
4592 static const struct snd_pci_quirk ad1884a_cfg_tbl
[] = {
4593 SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION
),
4594 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE
),
4595 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP
),
4596 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE
),
4597 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE
),
4598 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP
),
4599 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP
),
4600 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP
),
4601 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE
),
4602 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD
),
4603 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART
),
4607 static int patch_ad1884a(struct hda_codec
*codec
)
4609 struct ad198x_spec
*spec
;
4610 int err
, board_config
;
4612 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4618 err
= snd_hda_attach_beep_device(codec
, 0x10);
4623 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
4625 spec
->multiout
.max_channels
= 2;
4626 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884a_dac_nids
);
4627 spec
->multiout
.dac_nids
= ad1884a_dac_nids
;
4628 spec
->multiout
.dig_out_nid
= AD1884A_SPDIF_OUT
;
4629 spec
->num_adc_nids
= ARRAY_SIZE(ad1884a_adc_nids
);
4630 spec
->adc_nids
= ad1884a_adc_nids
;
4631 spec
->capsrc_nids
= ad1884a_capsrc_nids
;
4632 spec
->input_mux
= &ad1884a_capture_source
;
4633 spec
->num_mixers
= 1;
4634 spec
->mixers
[0] = ad1884a_base_mixers
;
4635 spec
->num_init_verbs
= 1;
4636 spec
->init_verbs
[0] = ad1884a_init_verbs
;
4637 spec
->spdif_route
= 0;
4638 #ifdef CONFIG_SND_HDA_POWER_SAVE
4639 spec
->loopback
.amplist
= ad1884a_loopbacks
;
4641 codec
->patch_ops
= ad198x_patch_ops
;
4643 /* override some parameters */
4644 board_config
= snd_hda_check_board_config(codec
, AD1884A_MODELS
,
4647 switch (board_config
) {
4648 case AD1884A_LAPTOP
:
4649 spec
->mixers
[0] = ad1884a_laptop_mixers
;
4650 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1884a_laptop_verbs
;
4651 spec
->multiout
.dig_out_nid
= 0;
4652 codec
->patch_ops
.unsol_event
= ad1884a_laptop_unsol_event
;
4653 codec
->patch_ops
.init
= ad1884a_laptop_init
;
4654 /* set the upper-limit for mixer amp to 0dB for avoiding the
4655 * possible damage by overloading
4657 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4658 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4659 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4660 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4661 (1 << AC_AMPCAP_MUTE_SHIFT
));
4663 case AD1884A_MOBILE
:
4664 spec
->mixers
[0] = ad1884a_mobile_mixers
;
4665 spec
->init_verbs
[0] = ad1884a_mobile_verbs
;
4666 spec
->multiout
.dig_out_nid
= 0;
4667 codec
->patch_ops
.unsol_event
= ad1884a_hp_unsol_event
;
4668 codec
->patch_ops
.init
= ad1884a_hp_init
;
4669 /* set the upper-limit for mixer amp to 0dB for avoiding the
4670 * possible damage by overloading
4672 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4673 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4674 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4675 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4676 (1 << AC_AMPCAP_MUTE_SHIFT
));
4678 case AD1884A_THINKPAD
:
4679 spec
->mixers
[0] = ad1984a_thinkpad_mixers
;
4680 spec
->init_verbs
[spec
->num_init_verbs
++] =
4681 ad1984a_thinkpad_verbs
;
4682 spec
->multiout
.dig_out_nid
= 0;
4683 spec
->input_mux
= &ad1984a_thinkpad_capture_source
;
4684 codec
->patch_ops
.unsol_event
= ad1984a_thinkpad_unsol_event
;
4685 codec
->patch_ops
.init
= ad1984a_thinkpad_init
;
4687 case AD1984A_PRECISION
:
4688 spec
->mixers
[0] = ad1984a_precision_mixers
;
4689 spec
->init_verbs
[spec
->num_init_verbs
++] =
4690 ad1984a_precision_verbs
;
4691 spec
->multiout
.dig_out_nid
= 0;
4692 codec
->patch_ops
.unsol_event
= ad1984a_precision_unsol_event
;
4693 codec
->patch_ops
.init
= ad1984a_precision_init
;
4695 case AD1984A_TOUCHSMART
:
4696 spec
->mixers
[0] = ad1984a_touchsmart_mixers
;
4697 spec
->init_verbs
[0] = ad1984a_touchsmart_verbs
;
4698 spec
->multiout
.dig_out_nid
= 0;
4699 codec
->patch_ops
.unsol_event
= ad1984a_touchsmart_unsol_event
;
4700 codec
->patch_ops
.init
= ad1984a_touchsmart_init
;
4701 /* set the upper-limit for mixer amp to 0dB for avoiding the
4702 * possible damage by overloading
4704 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4705 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4706 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4707 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4708 (1 << AC_AMPCAP_MUTE_SHIFT
));
4712 codec
->no_trigger_sense
= 1;
4713 codec
->no_sticky_stream
= 1;
4722 * port-A - front hp-out
4723 * port-B - front mic-in
4724 * port-C - rear line-in, shared surr-out (3stack)
4725 * port-D - rear line-out
4726 * port-E - rear mic-in, shared clfe-out (3stack)
4727 * port-F - rear surr-out (6stack)
4728 * port-G - rear clfe-out (6stack)
4731 static const hda_nid_t ad1882_dac_nids
[3] = {
4735 static const hda_nid_t ad1882_adc_nids
[2] = {
4739 static const hda_nid_t ad1882_capsrc_nids
[2] = {
4743 #define AD1882_SPDIF_OUT 0x02
4745 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4746 static const struct hda_input_mux ad1882_capture_source
= {
4749 { "Front Mic", 0x1 },
4757 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4758 static const struct hda_input_mux ad1882a_capture_source
= {
4761 { "Front Mic", 0x1 },
4764 { "Digital Mic", 0x06 },
4769 static const struct snd_kcontrol_new ad1882_base_mixers
[] = {
4770 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
4771 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
4772 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
4773 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
4774 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
4775 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
4776 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
4777 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
4779 HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT
),
4780 HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT
),
4781 HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT
),
4782 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4783 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4784 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
4785 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
4787 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4788 /* The multiple "Capture Source" controls confuse alsamixer
4789 * So call somewhat different..
4791 /* .name = "Capture Source", */
4792 .name
= "Input Source",
4794 .info
= ad198x_mux_enum_info
,
4795 .get
= ad198x_mux_enum_get
,
4796 .put
= ad198x_mux_enum_put
,
4798 /* SPDIF controls */
4799 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
4801 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4802 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
4803 /* identical with ad1983 */
4804 .info
= ad1983_spdif_route_info
,
4805 .get
= ad1983_spdif_route_get
,
4806 .put
= ad1983_spdif_route_put
,
4811 static const struct snd_kcontrol_new ad1882_loopback_mixers
[] = {
4812 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4813 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4814 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
4815 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
4816 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT
),
4817 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT
),
4818 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4819 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4823 static const struct snd_kcontrol_new ad1882a_loopback_mixers
[] = {
4824 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4825 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4826 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
4827 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
4828 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
4829 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
4830 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4831 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4832 HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT
),
4836 static const struct snd_kcontrol_new ad1882_3stack_mixers
[] = {
4837 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
4838 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT
),
4839 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT
),
4841 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4842 .name
= "Channel Mode",
4843 .info
= ad198x_ch_mode_info
,
4844 .get
= ad198x_ch_mode_get
,
4845 .put
= ad198x_ch_mode_put
,
4850 static const struct snd_kcontrol_new ad1882_6stack_mixers
[] = {
4851 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
4852 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT
),
4853 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT
),
4857 static const struct hda_verb ad1882_ch2_init
[] = {
4858 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4859 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4860 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4861 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4862 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4863 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4867 static const struct hda_verb ad1882_ch4_init
[] = {
4868 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4869 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4870 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4871 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4872 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4873 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4877 static const struct hda_verb ad1882_ch6_init
[] = {
4878 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4879 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4880 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4881 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4882 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4883 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4887 static const struct hda_channel_mode ad1882_modes
[3] = {
4888 { 2, ad1882_ch2_init
},
4889 { 4, ad1882_ch4_init
},
4890 { 6, ad1882_ch6_init
},
4894 * initialization verbs
4896 static const struct hda_verb ad1882_init_verbs
[] = {
4897 /* DACs; mute as default */
4898 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4899 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4900 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4901 /* Port-A (HP) mixer */
4902 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4903 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4905 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4906 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4907 /* HP selector - select DAC2 */
4908 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x1},
4909 /* Port-D (Line-out) mixer */
4910 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4911 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4913 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4914 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4915 /* Mono-out mixer */
4916 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4917 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4919 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4920 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4921 /* Port-B (front mic) pin */
4922 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4923 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4924 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4925 /* Port-C (line-in) pin */
4926 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4927 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4928 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4929 /* Port-C mixer - mute as input */
4930 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4931 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4932 /* Port-E (mic-in) pin */
4933 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4934 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4935 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4936 /* Port-E mixer - mute as input */
4937 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4938 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4939 /* Port-F (surround) */
4940 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4941 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4943 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4944 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4945 /* Analog mixer; mute as default */
4946 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4947 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4948 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4949 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4950 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4951 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4952 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4953 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
4954 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
4955 /* Analog Mix output amp */
4956 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
4957 /* SPDIF output selector */
4958 {0x02, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4959 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
4960 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4964 #ifdef CONFIG_SND_HDA_POWER_SAVE
4965 static const struct hda_amp_list ad1882_loopbacks
[] = {
4966 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
4967 { 0x20, HDA_INPUT
, 1 }, /* Mic */
4968 { 0x20, HDA_INPUT
, 4 }, /* Line */
4969 { 0x20, HDA_INPUT
, 6 }, /* CD */
4981 static const char * const ad1882_models
[AD1986A_MODELS
] = {
4982 [AD1882_3STACK
] = "3stack",
4983 [AD1882_6STACK
] = "6stack",
4987 static int patch_ad1882(struct hda_codec
*codec
)
4989 struct ad198x_spec
*spec
;
4990 int err
, board_config
;
4992 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4998 err
= snd_hda_attach_beep_device(codec
, 0x10);
5003 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
5005 spec
->multiout
.max_channels
= 6;
5006 spec
->multiout
.num_dacs
= 3;
5007 spec
->multiout
.dac_nids
= ad1882_dac_nids
;
5008 spec
->multiout
.dig_out_nid
= AD1882_SPDIF_OUT
;
5009 spec
->num_adc_nids
= ARRAY_SIZE(ad1882_adc_nids
);
5010 spec
->adc_nids
= ad1882_adc_nids
;
5011 spec
->capsrc_nids
= ad1882_capsrc_nids
;
5012 if (codec
->vendor_id
== 0x11d41882)
5013 spec
->input_mux
= &ad1882_capture_source
;
5015 spec
->input_mux
= &ad1882a_capture_source
;
5016 spec
->num_mixers
= 2;
5017 spec
->mixers
[0] = ad1882_base_mixers
;
5018 if (codec
->vendor_id
== 0x11d41882)
5019 spec
->mixers
[1] = ad1882_loopback_mixers
;
5021 spec
->mixers
[1] = ad1882a_loopback_mixers
;
5022 spec
->num_init_verbs
= 1;
5023 spec
->init_verbs
[0] = ad1882_init_verbs
;
5024 spec
->spdif_route
= 0;
5025 #ifdef CONFIG_SND_HDA_POWER_SAVE
5026 spec
->loopback
.amplist
= ad1882_loopbacks
;
5028 spec
->vmaster_nid
= 0x04;
5030 codec
->patch_ops
= ad198x_patch_ops
;
5032 /* override some parameters */
5033 board_config
= snd_hda_check_board_config(codec
, AD1882_MODELS
,
5034 ad1882_models
, NULL
);
5035 switch (board_config
) {
5038 spec
->num_mixers
= 3;
5039 spec
->mixers
[2] = ad1882_3stack_mixers
;
5040 spec
->channel_mode
= ad1882_modes
;
5041 spec
->num_channel_mode
= ARRAY_SIZE(ad1882_modes
);
5042 spec
->need_dac_fix
= 1;
5043 spec
->multiout
.max_channels
= 2;
5044 spec
->multiout
.num_dacs
= 1;
5047 spec
->num_mixers
= 3;
5048 spec
->mixers
[2] = ad1882_6stack_mixers
;
5052 codec
->no_trigger_sense
= 1;
5053 codec
->no_sticky_stream
= 1;
5062 static const struct hda_codec_preset snd_hda_preset_analog
[] = {
5063 { .id
= 0x11d4184a, .name
= "AD1884A", .patch
= patch_ad1884a
},
5064 { .id
= 0x11d41882, .name
= "AD1882", .patch
= patch_ad1882
},
5065 { .id
= 0x11d41883, .name
= "AD1883", .patch
= patch_ad1884a
},
5066 { .id
= 0x11d41884, .name
= "AD1884", .patch
= patch_ad1884
},
5067 { .id
= 0x11d4194a, .name
= "AD1984A", .patch
= patch_ad1884a
},
5068 { .id
= 0x11d4194b, .name
= "AD1984B", .patch
= patch_ad1884a
},
5069 { .id
= 0x11d41981, .name
= "AD1981", .patch
= patch_ad1981
},
5070 { .id
= 0x11d41983, .name
= "AD1983", .patch
= patch_ad1983
},
5071 { .id
= 0x11d41984, .name
= "AD1984", .patch
= patch_ad1984
},
5072 { .id
= 0x11d41986, .name
= "AD1986A", .patch
= patch_ad1986a
},
5073 { .id
= 0x11d41988, .name
= "AD1988", .patch
= patch_ad1988
},
5074 { .id
= 0x11d4198b, .name
= "AD1988B", .patch
= patch_ad1988
},
5075 { .id
= 0x11d4882a, .name
= "AD1882A", .patch
= patch_ad1882
},
5076 { .id
= 0x11d4989a, .name
= "AD1989A", .patch
= patch_ad1988
},
5077 { .id
= 0x11d4989b, .name
= "AD1989B", .patch
= patch_ad1988
},
5081 MODULE_ALIAS("snd-hda-codec-id:11d4*");
5083 MODULE_LICENSE("GPL");
5084 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
5086 static struct hda_codec_preset_list analog_list
= {
5087 .preset
= snd_hda_preset_analog
,
5088 .owner
= THIS_MODULE
,
5091 static int __init
patch_analog_init(void)
5093 return snd_hda_add_codec_preset(&analog_list
);
5096 static void __exit
patch_analog_exit(void)
5098 snd_hda_delete_codec_preset(&analog_list
);
5101 module_init(patch_analog_init
)
5102 module_exit(patch_analog_exit
)