2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
33 struct snd_kcontrol_new
*mixers
[5];
35 unsigned int beep_amp
; /* beep amp value, set via set_beep_amp() */
36 const struct hda_verb
*init_verbs
[5]; /* initialization verbs
37 * don't forget NULL termination!
39 unsigned int num_init_verbs
;
42 struct hda_multi_out multiout
; /* playback set-up
43 * max_channels, dacs must be set
44 * dig_out_nid and hp_nid are optional
46 unsigned int cur_eapd
;
47 unsigned int need_dac_fix
;
50 unsigned int num_adc_nids
;
52 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
55 const struct hda_input_mux
*input_mux
;
56 hda_nid_t
*capsrc_nids
;
57 unsigned int cur_mux
[3];
60 const struct hda_channel_mode
*channel_mode
;
64 struct hda_pcm pcm_rec
[3]; /* used in alc_build_pcms() */
66 unsigned int spdif_route
;
68 /* dynamic controls, init_verbs and input_mux */
69 struct auto_pin_cfg autocfg
;
70 struct snd_array kctls
;
71 struct hda_input_mux private_imux
;
72 hda_nid_t private_dac_nids
[AUTO_CFG_MAX_OUTS
];
74 unsigned int jack_present
:1;
75 unsigned int inv_jack_detect
:1;
77 #ifdef CONFIG_SND_HDA_POWER_SAVE
78 struct hda_loopback_check loopback
;
80 /* for virtual master */
81 hda_nid_t vmaster_nid
;
82 const char **slave_vols
;
83 const char **slave_sws
;
87 * input MUX handling (common part)
89 static int ad198x_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
91 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
92 struct ad198x_spec
*spec
= codec
->spec
;
94 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
97 static int ad198x_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
99 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
100 struct ad198x_spec
*spec
= codec
->spec
;
101 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
103 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
107 static int ad198x_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
109 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
110 struct ad198x_spec
*spec
= codec
->spec
;
111 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
113 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
114 spec
->capsrc_nids
[adc_idx
],
115 &spec
->cur_mux
[adc_idx
]);
119 * initialization (common callbacks)
121 static int ad198x_init(struct hda_codec
*codec
)
123 struct ad198x_spec
*spec
= codec
->spec
;
126 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
127 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
131 static const char *ad_slave_vols
[] = {
132 "Front Playback Volume",
133 "Surround Playback Volume",
134 "Center Playback Volume",
135 "LFE Playback Volume",
136 "Side Playback Volume",
137 "Headphone Playback Volume",
138 "Mono Playback Volume",
139 "Speaker Playback Volume",
140 "IEC958 Playback Volume",
144 static const char *ad_slave_sws
[] = {
145 "Front Playback Switch",
146 "Surround Playback Switch",
147 "Center Playback Switch",
148 "LFE Playback Switch",
149 "Side Playback Switch",
150 "Headphone Playback Switch",
151 "Mono Playback Switch",
152 "Speaker Playback Switch",
153 "IEC958 Playback Switch",
157 static void ad198x_free_kctls(struct hda_codec
*codec
);
159 /* additional beep mixers; the actual parameters are overwritten at build */
160 static struct snd_kcontrol_new ad_beep_mixer
[] = {
161 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT
),
162 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT
),
166 #define set_beep_amp(spec, nid, idx, dir) \
167 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
169 static int ad198x_build_controls(struct hda_codec
*codec
)
171 struct ad198x_spec
*spec
= codec
->spec
;
175 for (i
= 0; i
< spec
->num_mixers
; i
++) {
176 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
180 if (spec
->multiout
.dig_out_nid
) {
181 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
184 err
= snd_hda_create_spdif_share_sw(codec
,
188 spec
->multiout
.share_spdif
= 1;
190 if (spec
->dig_in_nid
) {
191 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
196 /* create beep controls if needed */
197 if (spec
->beep_amp
) {
198 struct snd_kcontrol_new
*knew
;
199 for (knew
= ad_beep_mixer
; knew
->name
; knew
++) {
200 struct snd_kcontrol
*kctl
;
201 kctl
= snd_ctl_new1(knew
, codec
);
204 kctl
->private_value
= spec
->beep_amp
;
205 err
= snd_hda_ctl_add(codec
,
206 get_amp_nid_(spec
->beep_amp
),
213 /* if we have no master control, let's create it */
214 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Volume")) {
215 unsigned int vmaster_tlv
[4];
216 snd_hda_set_vmaster_tlv(codec
, spec
->vmaster_nid
,
217 HDA_OUTPUT
, vmaster_tlv
);
218 err
= snd_hda_add_vmaster(codec
, "Master Playback Volume",
221 spec
->slave_vols
: ad_slave_vols
));
225 if (!snd_hda_find_mixer_ctl(codec
, "Master Playback Switch")) {
226 err
= snd_hda_add_vmaster(codec
, "Master Playback Switch",
229 spec
->slave_sws
: ad_slave_sws
));
234 ad198x_free_kctls(codec
); /* no longer needed */
238 #ifdef CONFIG_SND_HDA_POWER_SAVE
239 static int ad198x_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
241 struct ad198x_spec
*spec
= codec
->spec
;
242 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
247 * Analog playback callbacks
249 static int ad198x_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
250 struct hda_codec
*codec
,
251 struct snd_pcm_substream
*substream
)
253 struct ad198x_spec
*spec
= codec
->spec
;
254 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
258 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
259 struct hda_codec
*codec
,
260 unsigned int stream_tag
,
262 struct snd_pcm_substream
*substream
)
264 struct ad198x_spec
*spec
= codec
->spec
;
265 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
269 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
270 struct hda_codec
*codec
,
271 struct snd_pcm_substream
*substream
)
273 struct ad198x_spec
*spec
= codec
->spec
;
274 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
280 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
281 struct hda_codec
*codec
,
282 struct snd_pcm_substream
*substream
)
284 struct ad198x_spec
*spec
= codec
->spec
;
285 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
288 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
289 struct hda_codec
*codec
,
290 struct snd_pcm_substream
*substream
)
292 struct ad198x_spec
*spec
= codec
->spec
;
293 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
296 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
297 struct hda_codec
*codec
,
298 unsigned int stream_tag
,
300 struct snd_pcm_substream
*substream
)
302 struct ad198x_spec
*spec
= codec
->spec
;
303 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
307 static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
308 struct hda_codec
*codec
,
309 struct snd_pcm_substream
*substream
)
311 struct ad198x_spec
*spec
= codec
->spec
;
312 return snd_hda_multi_out_dig_cleanup(codec
, &spec
->multiout
);
318 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
319 struct hda_codec
*codec
,
320 unsigned int stream_tag
,
322 struct snd_pcm_substream
*substream
)
324 struct ad198x_spec
*spec
= codec
->spec
;
325 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
326 stream_tag
, 0, format
);
330 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
331 struct hda_codec
*codec
,
332 struct snd_pcm_substream
*substream
)
334 struct ad198x_spec
*spec
= codec
->spec
;
335 snd_hda_codec_cleanup_stream(codec
, spec
->adc_nids
[substream
->number
]);
342 static struct hda_pcm_stream ad198x_pcm_analog_playback
= {
345 .channels_max
= 6, /* changed later */
346 .nid
= 0, /* fill later */
348 .open
= ad198x_playback_pcm_open
,
349 .prepare
= ad198x_playback_pcm_prepare
,
350 .cleanup
= ad198x_playback_pcm_cleanup
354 static struct hda_pcm_stream ad198x_pcm_analog_capture
= {
358 .nid
= 0, /* fill later */
360 .prepare
= ad198x_capture_pcm_prepare
,
361 .cleanup
= ad198x_capture_pcm_cleanup
365 static struct hda_pcm_stream ad198x_pcm_digital_playback
= {
369 .nid
= 0, /* fill later */
371 .open
= ad198x_dig_playback_pcm_open
,
372 .close
= ad198x_dig_playback_pcm_close
,
373 .prepare
= ad198x_dig_playback_pcm_prepare
,
374 .cleanup
= ad198x_dig_playback_pcm_cleanup
378 static struct hda_pcm_stream ad198x_pcm_digital_capture
= {
382 /* NID is set in alc_build_pcms */
385 static int ad198x_build_pcms(struct hda_codec
*codec
)
387 struct ad198x_spec
*spec
= codec
->spec
;
388 struct hda_pcm
*info
= spec
->pcm_rec
;
391 codec
->pcm_info
= info
;
393 info
->name
= "AD198x Analog";
394 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_analog_playback
;
395 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->multiout
.max_channels
;
396 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
397 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_analog_capture
;
398 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_adc_nids
;
399 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
401 if (spec
->multiout
.dig_out_nid
) {
404 info
->name
= "AD198x Digital";
405 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
406 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ad198x_pcm_digital_playback
;
407 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
408 if (spec
->dig_in_nid
) {
409 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad198x_pcm_digital_capture
;
410 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
417 static void ad198x_free_kctls(struct hda_codec
*codec
)
419 struct ad198x_spec
*spec
= codec
->spec
;
421 if (spec
->kctls
.list
) {
422 struct snd_kcontrol_new
*kctl
= spec
->kctls
.list
;
424 for (i
= 0; i
< spec
->kctls
.used
; i
++)
427 snd_array_free(&spec
->kctls
);
430 static void ad198x_free(struct hda_codec
*codec
)
432 struct ad198x_spec
*spec
= codec
->spec
;
437 ad198x_free_kctls(codec
);
439 snd_hda_detach_beep_device(codec
);
442 static struct hda_codec_ops ad198x_patch_ops
= {
443 .build_controls
= ad198x_build_controls
,
444 .build_pcms
= ad198x_build_pcms
,
447 #ifdef CONFIG_SND_HDA_POWER_SAVE
448 .check_power_status
= ad198x_check_power_status
,
455 * the private value = nid | (invert << 8)
457 #define ad198x_eapd_info snd_ctl_boolean_mono_info
459 static int ad198x_eapd_get(struct snd_kcontrol
*kcontrol
,
460 struct snd_ctl_elem_value
*ucontrol
)
462 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
463 struct ad198x_spec
*spec
= codec
->spec
;
464 int invert
= (kcontrol
->private_value
>> 8) & 1;
466 ucontrol
->value
.integer
.value
[0] = ! spec
->cur_eapd
;
468 ucontrol
->value
.integer
.value
[0] = spec
->cur_eapd
;
472 static int ad198x_eapd_put(struct snd_kcontrol
*kcontrol
,
473 struct snd_ctl_elem_value
*ucontrol
)
475 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
476 struct ad198x_spec
*spec
= codec
->spec
;
477 int invert
= (kcontrol
->private_value
>> 8) & 1;
478 hda_nid_t nid
= kcontrol
->private_value
& 0xff;
480 eapd
= !!ucontrol
->value
.integer
.value
[0];
483 if (eapd
== spec
->cur_eapd
)
485 spec
->cur_eapd
= eapd
;
486 snd_hda_codec_write_cache(codec
, nid
,
487 0, AC_VERB_SET_EAPD_BTLENABLE
,
492 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
493 struct snd_ctl_elem_info
*uinfo
);
494 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
495 struct snd_ctl_elem_value
*ucontrol
);
496 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
497 struct snd_ctl_elem_value
*ucontrol
);
504 #define AD1986A_SPDIF_OUT 0x02
505 #define AD1986A_FRONT_DAC 0x03
506 #define AD1986A_SURR_DAC 0x04
507 #define AD1986A_CLFE_DAC 0x05
508 #define AD1986A_ADC 0x06
510 static hda_nid_t ad1986a_dac_nids
[3] = {
511 AD1986A_FRONT_DAC
, AD1986A_SURR_DAC
, AD1986A_CLFE_DAC
513 static hda_nid_t ad1986a_adc_nids
[1] = { AD1986A_ADC
};
514 static hda_nid_t ad1986a_capsrc_nids
[1] = { 0x12 };
516 static struct hda_input_mux ad1986a_capture_source
= {
530 static struct hda_bind_ctls ad1986a_bind_pcm_vol
= {
531 .ops
= &snd_hda_bind_vol
,
533 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
534 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
535 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
540 static struct hda_bind_ctls ad1986a_bind_pcm_sw
= {
541 .ops
= &snd_hda_bind_sw
,
543 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC
, 3, 0, HDA_OUTPUT
),
544 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC
, 3, 0, HDA_OUTPUT
),
545 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC
, 3, 0, HDA_OUTPUT
),
553 static struct snd_kcontrol_new ad1986a_mixers
[] = {
555 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
557 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol
),
558 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw
),
559 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
560 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
561 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
562 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
563 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT
),
564 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT
),
565 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT
),
566 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT
),
567 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT
),
568 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT
),
569 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
570 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
571 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
572 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
573 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
574 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
575 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
576 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
577 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT
),
578 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT
),
579 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT
),
580 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
581 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
583 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
584 .name
= "Capture Source",
585 .info
= ad198x_mux_enum_info
,
586 .get
= ad198x_mux_enum_get
,
587 .put
= ad198x_mux_enum_put
,
589 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT
),
593 /* additional mixers for 3stack mode */
594 static struct snd_kcontrol_new ad1986a_3st_mixers
[] = {
596 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
597 .name
= "Channel Mode",
598 .info
= ad198x_ch_mode_info
,
599 .get
= ad198x_ch_mode_get
,
600 .put
= ad198x_ch_mode_put
,
605 /* laptop model - 2ch only */
606 static hda_nid_t ad1986a_laptop_dac_nids
[1] = { AD1986A_FRONT_DAC
};
608 /* master controls both pins 0x1a and 0x1b */
609 static struct hda_bind_ctls ad1986a_laptop_master_vol
= {
610 .ops
= &snd_hda_bind_vol
,
612 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
613 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
618 static struct hda_bind_ctls ad1986a_laptop_master_sw
= {
619 .ops
= &snd_hda_bind_sw
,
621 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
622 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT
),
627 static struct snd_kcontrol_new ad1986a_laptop_mixers
[] = {
628 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
629 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
630 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
631 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
632 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT
),
633 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
634 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT
),
635 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT
),
636 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT
),
637 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
638 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
639 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
640 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT
),
642 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
643 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
644 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
645 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
647 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
648 .name
= "Capture Source",
649 .info
= ad198x_mux_enum_info
,
650 .get
= ad198x_mux_enum_get
,
651 .put
= ad198x_mux_enum_put
,
656 /* laptop-eapd model - 2ch only */
658 static struct hda_input_mux ad1986a_laptop_eapd_capture_source
= {
662 { "Internal Mic", 0x4 },
667 static struct hda_input_mux ad1986a_automic_capture_source
= {
675 static struct snd_kcontrol_new ad1986a_laptop_master_mixers
[] = {
676 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
677 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw
),
681 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers
[] = {
682 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
683 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
684 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
685 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
686 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT
),
687 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
688 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT
),
690 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
691 .name
= "Capture Source",
692 .info
= ad198x_mux_enum_info
,
693 .get
= ad198x_mux_enum_get
,
694 .put
= ad198x_mux_enum_put
,
697 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
698 .name
= "External Amplifier",
699 .info
= ad198x_eapd_info
,
700 .get
= ad198x_eapd_get
,
701 .put
= ad198x_eapd_put
,
702 .private_value
= 0x1b | (1 << 8), /* port-D, inversed */
707 static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers
[] = {
708 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT
),
709 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT
),
713 /* re-connect the mic boost input according to the jack sensing */
714 static void ad1986a_automic(struct hda_codec
*codec
)
716 unsigned int present
;
717 present
= snd_hda_codec_read(codec
, 0x1f, 0, AC_VERB_GET_PIN_SENSE
, 0);
718 /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
719 snd_hda_codec_write(codec
, 0x0f, 0, AC_VERB_SET_CONNECT_SEL
,
720 (present
& AC_PINSENSE_PRESENCE
) ? 0 : 2);
723 #define AD1986A_MIC_EVENT 0x36
725 static void ad1986a_automic_unsol_event(struct hda_codec
*codec
,
728 if ((res
>> 26) != AD1986A_MIC_EVENT
)
730 ad1986a_automic(codec
);
733 static int ad1986a_automic_init(struct hda_codec
*codec
)
736 ad1986a_automic(codec
);
740 /* laptop-automute - 2ch only */
742 static void ad1986a_update_hp(struct hda_codec
*codec
)
744 struct ad198x_spec
*spec
= codec
->spec
;
747 if (spec
->jack_present
)
748 mute
= HDA_AMP_MUTE
; /* mute internal speaker */
750 /* unmute internal speaker if necessary */
751 mute
= snd_hda_codec_amp_read(codec
, 0x1a, 0, HDA_OUTPUT
, 0);
752 snd_hda_codec_amp_stereo(codec
, 0x1b, HDA_OUTPUT
, 0,
756 static void ad1986a_hp_automute(struct hda_codec
*codec
)
758 struct ad198x_spec
*spec
= codec
->spec
;
759 unsigned int present
;
761 present
= snd_hda_codec_read(codec
, 0x1a, 0, AC_VERB_GET_PIN_SENSE
, 0);
762 spec
->jack_present
= !!(present
& 0x80000000);
763 if (spec
->inv_jack_detect
)
764 spec
->jack_present
= !spec
->jack_present
;
765 ad1986a_update_hp(codec
);
768 #define AD1986A_HP_EVENT 0x37
770 static void ad1986a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
772 if ((res
>> 26) != AD1986A_HP_EVENT
)
774 ad1986a_hp_automute(codec
);
777 static int ad1986a_hp_init(struct hda_codec
*codec
)
780 ad1986a_hp_automute(codec
);
784 /* bind hp and internal speaker mute (with plug check) */
785 static int ad1986a_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
786 struct snd_ctl_elem_value
*ucontrol
)
788 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
789 long *valp
= ucontrol
->value
.integer
.value
;
792 change
= snd_hda_codec_amp_update(codec
, 0x1a, 0, HDA_OUTPUT
, 0,
794 valp
[0] ? 0 : HDA_AMP_MUTE
);
795 change
|= snd_hda_codec_amp_update(codec
, 0x1a, 1, HDA_OUTPUT
, 0,
797 valp
[1] ? 0 : HDA_AMP_MUTE
);
799 ad1986a_update_hp(codec
);
803 static struct snd_kcontrol_new ad1986a_automute_master_mixers
[] = {
804 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol
),
806 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
807 .name
= "Master Playback Switch",
808 .info
= snd_hda_mixer_amp_switch_info
,
809 .get
= snd_hda_mixer_amp_switch_get
,
810 .put
= ad1986a_hp_master_sw_put
,
811 .private_value
= HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
),
818 * initialization verbs
820 static struct hda_verb ad1986a_init_verbs
[] = {
821 /* Front, Surround, CLFE DAC; mute as default */
822 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
823 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
824 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
826 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
827 /* HP, Line-Out, Surround, CLFE selectors */
828 {0x0a, AC_VERB_SET_CONNECT_SEL
, 0x0},
829 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0},
830 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
831 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
833 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x0},
834 /* Mic selector: Mic 1/2 pin */
835 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
836 /* Line-in selector: Line-in */
837 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x0},
839 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x0},
840 /* Record selector: mic */
841 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x0},
842 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
843 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
844 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
845 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
846 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
847 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
849 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x0},
850 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
851 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
852 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
853 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
854 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
855 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
857 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
858 /* Front, Surround, CLFE Pins */
859 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
860 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
861 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
863 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
865 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
866 /* Line, Aux, CD, Beep-In Pin */
867 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
868 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
869 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
870 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
871 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
875 static struct hda_verb ad1986a_ch2_init
[] = {
876 /* Surround out -> Line In */
877 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
878 /* Line-in selectors */
879 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x1 },
881 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
882 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
883 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
887 static struct hda_verb ad1986a_ch4_init
[] = {
888 /* Surround out -> Surround */
889 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
890 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
892 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
893 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x4 },
897 static struct hda_verb ad1986a_ch6_init
[] = {
898 /* Surround out -> Surround out */
899 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
900 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x0 },
902 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
903 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0 },
907 static struct hda_channel_mode ad1986a_modes
[3] = {
908 { 2, ad1986a_ch2_init
},
909 { 4, ad1986a_ch4_init
},
910 { 6, ad1986a_ch6_init
},
913 /* eapd initialization */
914 static struct hda_verb ad1986a_eapd_init_verbs
[] = {
915 {0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
919 static struct hda_verb ad1986a_automic_verbs
[] = {
920 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
921 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
922 /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
923 {0x0f, AC_VERB_SET_CONNECT_SEL
, 0x0},
924 {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_MIC_EVENT
},
928 /* Ultra initialization */
929 static struct hda_verb ad1986a_ultra_init
[] = {
930 /* eapd initialization */
931 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 },
933 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x2 },
934 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
935 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
939 /* pin sensing on HP jack */
940 static struct hda_verb ad1986a_hp_init_verbs
[] = {
941 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1986A_HP_EVENT
},
945 static void ad1986a_samsung_p50_unsol_event(struct hda_codec
*codec
,
949 case AD1986A_HP_EVENT
:
950 ad1986a_hp_automute(codec
);
952 case AD1986A_MIC_EVENT
:
953 ad1986a_automic(codec
);
958 static int ad1986a_samsung_p50_init(struct hda_codec
*codec
)
961 ad1986a_hp_automute(codec
);
962 ad1986a_automic(codec
);
973 AD1986A_LAPTOP_AUTOMUTE
,
980 static const char *ad1986a_models
[AD1986A_MODELS
] = {
981 [AD1986A_6STACK
] = "6stack",
982 [AD1986A_3STACK
] = "3stack",
983 [AD1986A_LAPTOP
] = "laptop",
984 [AD1986A_LAPTOP_EAPD
] = "laptop-eapd",
985 [AD1986A_LAPTOP_AUTOMUTE
] = "laptop-automute",
986 [AD1986A_ULTRA
] = "ultra",
987 [AD1986A_SAMSUNG
] = "samsung",
988 [AD1986A_SAMSUNG_P50
] = "samsung-p50",
991 static struct snd_pci_quirk ad1986a_cfg_tbl
[] = {
992 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD
),
993 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD
),
994 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD
),
995 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD
),
996 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD
),
997 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD
),
998 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD
),
999 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD
),
1000 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP
),
1001 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK
),
1002 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK
),
1003 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP
),
1004 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK
),
1005 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK
),
1006 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK
),
1007 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK
),
1008 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD
),
1009 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK
),
1010 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP
),
1011 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50
),
1012 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA
),
1013 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG
),
1014 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK
),
1015 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP
),
1016 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK
),
1017 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE
),
1018 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP
),
1022 #ifdef CONFIG_SND_HDA_POWER_SAVE
1023 static struct hda_amp_list ad1986a_loopbacks
[] = {
1024 { 0x13, HDA_OUTPUT
, 0 }, /* Mic */
1025 { 0x14, HDA_OUTPUT
, 0 }, /* Phone */
1026 { 0x15, HDA_OUTPUT
, 0 }, /* CD */
1027 { 0x16, HDA_OUTPUT
, 0 }, /* Aux */
1028 { 0x17, HDA_OUTPUT
, 0 }, /* Line */
1033 static int is_jack_available(struct hda_codec
*codec
, hda_nid_t nid
)
1035 unsigned int conf
= snd_hda_codec_get_pincfg(codec
, nid
);
1036 return get_defcfg_connect(conf
) != AC_JACK_PORT_NONE
;
1039 static int patch_ad1986a(struct hda_codec
*codec
)
1041 struct ad198x_spec
*spec
;
1042 int err
, board_config
;
1044 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1050 err
= snd_hda_attach_beep_device(codec
, 0x19);
1055 set_beep_amp(spec
, 0x18, 0, HDA_OUTPUT
);
1057 spec
->multiout
.max_channels
= 6;
1058 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1986a_dac_nids
);
1059 spec
->multiout
.dac_nids
= ad1986a_dac_nids
;
1060 spec
->multiout
.dig_out_nid
= AD1986A_SPDIF_OUT
;
1061 spec
->num_adc_nids
= 1;
1062 spec
->adc_nids
= ad1986a_adc_nids
;
1063 spec
->capsrc_nids
= ad1986a_capsrc_nids
;
1064 spec
->input_mux
= &ad1986a_capture_source
;
1065 spec
->num_mixers
= 1;
1066 spec
->mixers
[0] = ad1986a_mixers
;
1067 spec
->num_init_verbs
= 1;
1068 spec
->init_verbs
[0] = ad1986a_init_verbs
;
1069 #ifdef CONFIG_SND_HDA_POWER_SAVE
1070 spec
->loopback
.amplist
= ad1986a_loopbacks
;
1072 spec
->vmaster_nid
= 0x1b;
1074 codec
->patch_ops
= ad198x_patch_ops
;
1076 /* override some parameters */
1077 board_config
= snd_hda_check_board_config(codec
, AD1986A_MODELS
,
1080 switch (board_config
) {
1081 case AD1986A_3STACK
:
1082 spec
->num_mixers
= 2;
1083 spec
->mixers
[1] = ad1986a_3st_mixers
;
1084 spec
->num_init_verbs
= 2;
1085 spec
->init_verbs
[1] = ad1986a_ch2_init
;
1086 spec
->channel_mode
= ad1986a_modes
;
1087 spec
->num_channel_mode
= ARRAY_SIZE(ad1986a_modes
);
1088 spec
->need_dac_fix
= 1;
1089 spec
->multiout
.max_channels
= 2;
1090 spec
->multiout
.num_dacs
= 1;
1092 case AD1986A_LAPTOP
:
1093 spec
->mixers
[0] = ad1986a_laptop_mixers
;
1094 spec
->multiout
.max_channels
= 2;
1095 spec
->multiout
.num_dacs
= 1;
1096 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1098 case AD1986A_LAPTOP_EAPD
:
1099 spec
->num_mixers
= 3;
1100 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1101 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1102 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1103 spec
->num_init_verbs
= 2;
1104 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1105 spec
->multiout
.max_channels
= 2;
1106 spec
->multiout
.num_dacs
= 1;
1107 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1108 if (!is_jack_available(codec
, 0x25))
1109 spec
->multiout
.dig_out_nid
= 0;
1110 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1112 case AD1986A_SAMSUNG
:
1113 spec
->num_mixers
= 2;
1114 spec
->mixers
[0] = ad1986a_laptop_master_mixers
;
1115 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1116 spec
->num_init_verbs
= 3;
1117 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1118 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1119 spec
->multiout
.max_channels
= 2;
1120 spec
->multiout
.num_dacs
= 1;
1121 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1122 if (!is_jack_available(codec
, 0x25))
1123 spec
->multiout
.dig_out_nid
= 0;
1124 spec
->input_mux
= &ad1986a_automic_capture_source
;
1125 codec
->patch_ops
.unsol_event
= ad1986a_automic_unsol_event
;
1126 codec
->patch_ops
.init
= ad1986a_automic_init
;
1128 case AD1986A_SAMSUNG_P50
:
1129 spec
->num_mixers
= 2;
1130 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1131 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1132 spec
->num_init_verbs
= 4;
1133 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1134 spec
->init_verbs
[2] = ad1986a_automic_verbs
;
1135 spec
->init_verbs
[3] = ad1986a_hp_init_verbs
;
1136 spec
->multiout
.max_channels
= 2;
1137 spec
->multiout
.num_dacs
= 1;
1138 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1139 if (!is_jack_available(codec
, 0x25))
1140 spec
->multiout
.dig_out_nid
= 0;
1141 spec
->input_mux
= &ad1986a_automic_capture_source
;
1142 codec
->patch_ops
.unsol_event
= ad1986a_samsung_p50_unsol_event
;
1143 codec
->patch_ops
.init
= ad1986a_samsung_p50_init
;
1145 case AD1986A_LAPTOP_AUTOMUTE
:
1146 spec
->num_mixers
= 3;
1147 spec
->mixers
[0] = ad1986a_automute_master_mixers
;
1148 spec
->mixers
[1] = ad1986a_laptop_eapd_mixers
;
1149 spec
->mixers
[2] = ad1986a_laptop_intmic_mixers
;
1150 spec
->num_init_verbs
= 3;
1151 spec
->init_verbs
[1] = ad1986a_eapd_init_verbs
;
1152 spec
->init_verbs
[2] = ad1986a_hp_init_verbs
;
1153 spec
->multiout
.max_channels
= 2;
1154 spec
->multiout
.num_dacs
= 1;
1155 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1156 if (!is_jack_available(codec
, 0x25))
1157 spec
->multiout
.dig_out_nid
= 0;
1158 spec
->input_mux
= &ad1986a_laptop_eapd_capture_source
;
1159 codec
->patch_ops
.unsol_event
= ad1986a_hp_unsol_event
;
1160 codec
->patch_ops
.init
= ad1986a_hp_init
;
1161 /* Lenovo N100 seems to report the reversed bit
1162 * for HP jack-sensing
1164 spec
->inv_jack_detect
= 1;
1167 spec
->mixers
[0] = ad1986a_laptop_eapd_mixers
;
1168 spec
->num_init_verbs
= 2;
1169 spec
->init_verbs
[1] = ad1986a_ultra_init
;
1170 spec
->multiout
.max_channels
= 2;
1171 spec
->multiout
.num_dacs
= 1;
1172 spec
->multiout
.dac_nids
= ad1986a_laptop_dac_nids
;
1173 spec
->multiout
.dig_out_nid
= 0;
1177 /* AD1986A has a hardware problem that it can't share a stream
1178 * with multiple output pins. The copy of front to surrounds
1179 * causes noisy or silent outputs at a certain timing, e.g.
1180 * changing the volume.
1181 * So, let's disable the shared stream.
1183 spec
->multiout
.no_share_stream
= 1;
1192 #define AD1983_SPDIF_OUT 0x02
1193 #define AD1983_DAC 0x03
1194 #define AD1983_ADC 0x04
1196 static hda_nid_t ad1983_dac_nids
[1] = { AD1983_DAC
};
1197 static hda_nid_t ad1983_adc_nids
[1] = { AD1983_ADC
};
1198 static hda_nid_t ad1983_capsrc_nids
[1] = { 0x15 };
1200 static struct hda_input_mux ad1983_capture_source
= {
1206 { "Mix Mono", 0x3 },
1211 * SPDIF playback route
1213 static int ad1983_spdif_route_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1215 static char *texts
[] = { "PCM", "ADC" };
1217 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1219 uinfo
->value
.enumerated
.items
= 2;
1220 if (uinfo
->value
.enumerated
.item
> 1)
1221 uinfo
->value
.enumerated
.item
= 1;
1222 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1226 static int ad1983_spdif_route_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1228 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1229 struct ad198x_spec
*spec
= codec
->spec
;
1231 ucontrol
->value
.enumerated
.item
[0] = spec
->spdif_route
;
1235 static int ad1983_spdif_route_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1237 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1238 struct ad198x_spec
*spec
= codec
->spec
;
1240 if (ucontrol
->value
.enumerated
.item
[0] > 1)
1242 if (spec
->spdif_route
!= ucontrol
->value
.enumerated
.item
[0]) {
1243 spec
->spdif_route
= ucontrol
->value
.enumerated
.item
[0];
1244 snd_hda_codec_write_cache(codec
, spec
->multiout
.dig_out_nid
, 0,
1245 AC_VERB_SET_CONNECT_SEL
,
1252 static struct snd_kcontrol_new ad1983_mixers
[] = {
1253 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1254 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1255 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1256 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1257 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1258 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1259 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1260 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1261 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1262 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1263 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1264 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1265 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT
),
1266 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1267 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1269 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1270 .name
= "Capture Source",
1271 .info
= ad198x_mux_enum_info
,
1272 .get
= ad198x_mux_enum_get
,
1273 .put
= ad198x_mux_enum_put
,
1276 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1277 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1278 .info
= ad1983_spdif_route_info
,
1279 .get
= ad1983_spdif_route_get
,
1280 .put
= ad1983_spdif_route_put
,
1285 static struct hda_verb ad1983_init_verbs
[] = {
1286 /* Front, HP, Mono; mute as default */
1287 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1288 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1289 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1290 /* Beep, PCM, Mic, Line-In: mute */
1291 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1292 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1293 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1294 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1295 /* Front, HP selectors; from Mix */
1296 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1297 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1298 /* Mono selector; from Mix */
1299 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1300 /* Mic selector; Mic */
1301 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
1302 /* Line-in selector: Line-in */
1303 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1304 /* Mic boost: 0dB */
1305 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1306 /* Record selector: mic */
1307 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1308 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1309 /* SPDIF route: PCM */
1310 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1312 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1314 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1316 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1318 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1320 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1324 #ifdef CONFIG_SND_HDA_POWER_SAVE
1325 static struct hda_amp_list ad1983_loopbacks
[] = {
1326 { 0x12, HDA_OUTPUT
, 0 }, /* Mic */
1327 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1332 static int patch_ad1983(struct hda_codec
*codec
)
1334 struct ad198x_spec
*spec
;
1337 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1343 err
= snd_hda_attach_beep_device(codec
, 0x10);
1348 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
1350 spec
->multiout
.max_channels
= 2;
1351 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1983_dac_nids
);
1352 spec
->multiout
.dac_nids
= ad1983_dac_nids
;
1353 spec
->multiout
.dig_out_nid
= AD1983_SPDIF_OUT
;
1354 spec
->num_adc_nids
= 1;
1355 spec
->adc_nids
= ad1983_adc_nids
;
1356 spec
->capsrc_nids
= ad1983_capsrc_nids
;
1357 spec
->input_mux
= &ad1983_capture_source
;
1358 spec
->num_mixers
= 1;
1359 spec
->mixers
[0] = ad1983_mixers
;
1360 spec
->num_init_verbs
= 1;
1361 spec
->init_verbs
[0] = ad1983_init_verbs
;
1362 spec
->spdif_route
= 0;
1363 #ifdef CONFIG_SND_HDA_POWER_SAVE
1364 spec
->loopback
.amplist
= ad1983_loopbacks
;
1366 spec
->vmaster_nid
= 0x05;
1368 codec
->patch_ops
= ad198x_patch_ops
;
1375 * AD1981 HD specific
1378 #define AD1981_SPDIF_OUT 0x02
1379 #define AD1981_DAC 0x03
1380 #define AD1981_ADC 0x04
1382 static hda_nid_t ad1981_dac_nids
[1] = { AD1981_DAC
};
1383 static hda_nid_t ad1981_adc_nids
[1] = { AD1981_ADC
};
1384 static hda_nid_t ad1981_capsrc_nids
[1] = { 0x15 };
1386 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1387 static struct hda_input_mux ad1981_capture_source
= {
1390 { "Front Mic", 0x0 },
1393 { "Mix Mono", 0x3 },
1400 static struct snd_kcontrol_new ad1981_mixers
[] = {
1401 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1402 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1403 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
1404 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
1405 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT
),
1406 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT
),
1407 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1408 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1409 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1410 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1411 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1412 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1413 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
1414 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
1415 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1416 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1417 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1418 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1419 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT
),
1420 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT
),
1421 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1422 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1424 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1425 .name
= "Capture Source",
1426 .info
= ad198x_mux_enum_info
,
1427 .get
= ad198x_mux_enum_get
,
1428 .put
= ad198x_mux_enum_put
,
1430 /* identical with AD1983 */
1432 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1433 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1434 .info
= ad1983_spdif_route_info
,
1435 .get
= ad1983_spdif_route_get
,
1436 .put
= ad1983_spdif_route_put
,
1441 static struct hda_verb ad1981_init_verbs
[] = {
1442 /* Front, HP, Mono; mute as default */
1443 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1444 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1445 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1446 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1447 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1448 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1449 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1450 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1451 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1452 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1453 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1454 /* Front, HP selectors; from Mix */
1455 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x01},
1456 {0x06, AC_VERB_SET_CONNECT_SEL
, 0x01},
1457 /* Mono selector; from Mix */
1458 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x03},
1459 /* Mic Mixer; select Front Mic */
1460 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1461 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1462 /* Mic boost: 0dB */
1463 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1464 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1465 /* Record selector: Front mic */
1466 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x0},
1467 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1468 /* SPDIF route: PCM */
1469 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0},
1471 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1473 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
1475 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
1476 /* Front & Rear Mic Pins */
1477 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1478 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
1480 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
1482 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00},
1483 /* Line-Out as Input: disabled */
1484 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1488 #ifdef CONFIG_SND_HDA_POWER_SAVE
1489 static struct hda_amp_list ad1981_loopbacks
[] = {
1490 { 0x12, HDA_OUTPUT
, 0 }, /* Front Mic */
1491 { 0x13, HDA_OUTPUT
, 0 }, /* Line */
1492 { 0x1b, HDA_OUTPUT
, 0 }, /* Aux */
1493 { 0x1c, HDA_OUTPUT
, 0 }, /* Mic */
1494 { 0x1d, HDA_OUTPUT
, 0 }, /* CD */
1500 * Patch for HP nx6320
1502 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1503 * speaker output enabled _and_ mute-LED off.
1506 #define AD1981_HP_EVENT 0x37
1507 #define AD1981_MIC_EVENT 0x38
1509 static struct hda_verb ad1981_hp_init_verbs
[] = {
1510 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x00 }, /* default off */
1511 /* pin sensing on HP and Mic jacks */
1512 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1513 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1517 /* turn on/off EAPD (+ mute HP) as a master switch */
1518 static int ad1981_hp_master_sw_put(struct snd_kcontrol
*kcontrol
,
1519 struct snd_ctl_elem_value
*ucontrol
)
1521 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1522 struct ad198x_spec
*spec
= codec
->spec
;
1524 if (! ad198x_eapd_put(kcontrol
, ucontrol
))
1526 /* change speaker pin appropriately */
1527 snd_hda_codec_write(codec
, 0x05, 0,
1528 AC_VERB_SET_PIN_WIDGET_CONTROL
,
1529 spec
->cur_eapd
? PIN_OUT
: 0);
1530 /* toggle HP mute appropriately */
1531 snd_hda_codec_amp_stereo(codec
, 0x06, HDA_OUTPUT
, 0,
1533 spec
->cur_eapd
? 0 : HDA_AMP_MUTE
);
1537 /* bind volumes of both NID 0x05 and 0x06 */
1538 static struct hda_bind_ctls ad1981_hp_bind_master_vol
= {
1539 .ops
= &snd_hda_bind_vol
,
1541 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT
),
1542 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT
),
1547 /* mute internal speaker if HP is plugged */
1548 static void ad1981_hp_automute(struct hda_codec
*codec
)
1550 unsigned int present
;
1552 present
= snd_hda_codec_read(codec
, 0x06, 0,
1553 AC_VERB_GET_PIN_SENSE
, 0) & 0x80000000;
1554 snd_hda_codec_amp_stereo(codec
, 0x05, HDA_OUTPUT
, 0,
1555 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
1558 /* toggle input of built-in and mic jack appropriately */
1559 static void ad1981_hp_automic(struct hda_codec
*codec
)
1561 static struct hda_verb mic_jack_on
[] = {
1562 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1563 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1566 static struct hda_verb mic_jack_off
[] = {
1567 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080},
1568 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
1571 unsigned int present
;
1573 present
= snd_hda_codec_read(codec
, 0x08, 0,
1574 AC_VERB_GET_PIN_SENSE
, 0) & 0x80000000;
1576 snd_hda_sequence_write(codec
, mic_jack_on
);
1578 snd_hda_sequence_write(codec
, mic_jack_off
);
1581 /* unsolicited event for HP jack sensing */
1582 static void ad1981_hp_unsol_event(struct hda_codec
*codec
,
1587 case AD1981_HP_EVENT
:
1588 ad1981_hp_automute(codec
);
1590 case AD1981_MIC_EVENT
:
1591 ad1981_hp_automic(codec
);
1596 static struct hda_input_mux ad1981_hp_capture_source
= {
1600 { "Docking-Station", 0x1 },
1605 static struct snd_kcontrol_new ad1981_hp_mixers
[] = {
1606 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol
),
1608 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1609 .name
= "Master Playback Switch",
1610 .info
= ad198x_eapd_info
,
1611 .get
= ad198x_eapd_get
,
1612 .put
= ad1981_hp_master_sw_put
,
1613 .private_value
= 0x05,
1615 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1616 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1618 /* FIXME: analog mic/line loopback doesn't work with my tests...
1619 * (although recording is OK)
1621 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1622 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1623 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT
),
1624 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT
),
1625 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT
),
1626 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT
),
1627 /* FIXME: does this laptop have analog CD connection? */
1628 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1629 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1631 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT
),
1632 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT
),
1633 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1634 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1636 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1637 .name
= "Capture Source",
1638 .info
= ad198x_mux_enum_info
,
1639 .get
= ad198x_mux_enum_get
,
1640 .put
= ad198x_mux_enum_put
,
1645 /* initialize jack-sensing, too */
1646 static int ad1981_hp_init(struct hda_codec
*codec
)
1649 ad1981_hp_automute(codec
);
1650 ad1981_hp_automic(codec
);
1654 /* configuration for Toshiba Laptops */
1655 static struct hda_verb ad1981_toshiba_init_verbs
[] = {
1656 {0x05, AC_VERB_SET_EAPD_BTLENABLE
, 0x01 }, /* default on */
1657 /* pin sensing on HP and Mic jacks */
1658 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_HP_EVENT
},
1659 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1981_MIC_EVENT
},
1663 static struct snd_kcontrol_new ad1981_toshiba_mixers
[] = {
1664 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT
),
1665 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT
),
1669 /* configuration for Lenovo Thinkpad T60 */
1670 static struct snd_kcontrol_new ad1981_thinkpad_mixers
[] = {
1671 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
1672 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT
),
1673 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT
),
1674 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
1675 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT
),
1676 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
1677 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
1678 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT
),
1679 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT
),
1680 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
1681 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT
),
1683 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1684 .name
= "Capture Source",
1685 .info
= ad198x_mux_enum_info
,
1686 .get
= ad198x_mux_enum_get
,
1687 .put
= ad198x_mux_enum_put
,
1689 /* identical with AD1983 */
1691 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1692 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
1693 .info
= ad1983_spdif_route_info
,
1694 .get
= ad1983_spdif_route_get
,
1695 .put
= ad1983_spdif_route_put
,
1700 static struct hda_input_mux ad1981_thinkpad_capture_source
= {
1718 static const char *ad1981_models
[AD1981_MODELS
] = {
1720 [AD1981_THINKPAD
] = "thinkpad",
1721 [AD1981_BASIC
] = "basic",
1722 [AD1981_TOSHIBA
] = "toshiba"
1725 static struct snd_pci_quirk ad1981_cfg_tbl
[] = {
1726 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD
),
1727 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD
),
1729 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP
),
1730 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA
),
1731 /* Lenovo Thinkpad T60/X60/Z6xx */
1732 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD
),
1733 /* HP nx6320 (reversed SSID, H/W bug) */
1734 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP
),
1738 static int patch_ad1981(struct hda_codec
*codec
)
1740 struct ad198x_spec
*spec
;
1741 int err
, board_config
;
1743 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1749 err
= snd_hda_attach_beep_device(codec
, 0x10);
1754 set_beep_amp(spec
, 0x0d, 0, HDA_OUTPUT
);
1756 spec
->multiout
.max_channels
= 2;
1757 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1981_dac_nids
);
1758 spec
->multiout
.dac_nids
= ad1981_dac_nids
;
1759 spec
->multiout
.dig_out_nid
= AD1981_SPDIF_OUT
;
1760 spec
->num_adc_nids
= 1;
1761 spec
->adc_nids
= ad1981_adc_nids
;
1762 spec
->capsrc_nids
= ad1981_capsrc_nids
;
1763 spec
->input_mux
= &ad1981_capture_source
;
1764 spec
->num_mixers
= 1;
1765 spec
->mixers
[0] = ad1981_mixers
;
1766 spec
->num_init_verbs
= 1;
1767 spec
->init_verbs
[0] = ad1981_init_verbs
;
1768 spec
->spdif_route
= 0;
1769 #ifdef CONFIG_SND_HDA_POWER_SAVE
1770 spec
->loopback
.amplist
= ad1981_loopbacks
;
1772 spec
->vmaster_nid
= 0x05;
1774 codec
->patch_ops
= ad198x_patch_ops
;
1776 /* override some parameters */
1777 board_config
= snd_hda_check_board_config(codec
, AD1981_MODELS
,
1780 switch (board_config
) {
1782 spec
->mixers
[0] = ad1981_hp_mixers
;
1783 spec
->num_init_verbs
= 2;
1784 spec
->init_verbs
[1] = ad1981_hp_init_verbs
;
1785 spec
->multiout
.dig_out_nid
= 0;
1786 spec
->input_mux
= &ad1981_hp_capture_source
;
1788 codec
->patch_ops
.init
= ad1981_hp_init
;
1789 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
1791 case AD1981_THINKPAD
:
1792 spec
->mixers
[0] = ad1981_thinkpad_mixers
;
1793 spec
->input_mux
= &ad1981_thinkpad_capture_source
;
1795 case AD1981_TOSHIBA
:
1796 spec
->mixers
[0] = ad1981_hp_mixers
;
1797 spec
->mixers
[1] = ad1981_toshiba_mixers
;
1798 spec
->num_init_verbs
= 2;
1799 spec
->init_verbs
[1] = ad1981_toshiba_init_verbs
;
1800 spec
->multiout
.dig_out_nid
= 0;
1801 spec
->input_mux
= &ad1981_hp_capture_source
;
1802 codec
->patch_ops
.init
= ad1981_hp_init
;
1803 codec
->patch_ops
.unsol_event
= ad1981_hp_unsol_event
;
1813 * Output pins and routes
1815 * Pin Mix Sel DAC (*)
1816 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1817 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1818 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1819 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1820 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1821 * port-F 0x16 (mute) <- 0x2a <- 06
1822 * port-G 0x24 (mute) <- 0x27 <- 05
1823 * port-H 0x25 (mute) <- 0x28 <- 0a
1824 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1826 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1827 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1829 * Input pins and routes
1831 * pin boost mix input # / adc input #
1832 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1833 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1834 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1835 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1836 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1837 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1838 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1839 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1843 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
1844 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
1846 * Inputs of Analog Mix (0x20)
1847 * 0:Port-B (front mic)
1848 * 1:Port-C/G/H (line-in)
1850 * 3:Port-D (line-in/2)
1851 * 4:Port-E/G/H (mic-in)
1852 * 5:Port-F (mic2-in)
1858 * 1:Port-B (front mic-in)
1859 * 2:Port-C (line-in)
1860 * 3:Port-F (mic2-in)
1865 * 8:Port-D (line-in/2)
1868 * Proposed pin assignments by the datasheet
1871 * Port-A front headphone
1881 * Port-A front headphone
1883 * C rear line-in/surround
1885 * E rear mic-in/CLFE
1891 * D internal speaker (with EAPD)
1892 * E/F quad mic array
1908 /* reivision id to check workarounds */
1909 #define AD1988A_REV2 0x100200
1911 #define is_rev2(codec) \
1912 ((codec)->vendor_id == 0x11d41988 && \
1913 (codec)->revision_id == AD1988A_REV2)
1919 static hda_nid_t ad1988_6stack_dac_nids
[4] = {
1920 0x04, 0x06, 0x05, 0x0a
1923 static hda_nid_t ad1988_3stack_dac_nids
[3] = {
1927 /* for AD1988A revision-2, DAC2-4 are swapped */
1928 static hda_nid_t ad1988_6stack_dac_nids_rev2
[4] = {
1929 0x04, 0x05, 0x0a, 0x06
1932 static hda_nid_t ad1988_3stack_dac_nids_rev2
[3] = {
1936 static hda_nid_t ad1988_adc_nids
[3] = {
1940 static hda_nid_t ad1988_capsrc_nids
[3] = {
1944 #define AD1988_SPDIF_OUT 0x02
1945 #define AD1988_SPDIF_OUT_HDMI 0x0b
1946 #define AD1988_SPDIF_IN 0x07
1948 static hda_nid_t ad1989b_slave_dig_outs
[] = {
1949 AD1988_SPDIF_OUT
, AD1988_SPDIF_OUT_HDMI
, 0
1952 static struct hda_input_mux ad1988_6stack_capture_source
= {
1955 { "Front Mic", 0x1 }, /* port-B */
1956 { "Line", 0x2 }, /* port-C */
1957 { "Mic", 0x4 }, /* port-E */
1963 static struct hda_input_mux ad1988_laptop_capture_source
= {
1966 { "Mic/Line", 0x1 }, /* port-B */
1974 static int ad198x_ch_mode_info(struct snd_kcontrol
*kcontrol
,
1975 struct snd_ctl_elem_info
*uinfo
)
1977 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1978 struct ad198x_spec
*spec
= codec
->spec
;
1979 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
1980 spec
->num_channel_mode
);
1983 static int ad198x_ch_mode_get(struct snd_kcontrol
*kcontrol
,
1984 struct snd_ctl_elem_value
*ucontrol
)
1986 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1987 struct ad198x_spec
*spec
= codec
->spec
;
1988 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
1989 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
1992 static int ad198x_ch_mode_put(struct snd_kcontrol
*kcontrol
,
1993 struct snd_ctl_elem_value
*ucontrol
)
1995 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1996 struct ad198x_spec
*spec
= codec
->spec
;
1997 int err
= snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
1998 spec
->num_channel_mode
,
1999 &spec
->multiout
.max_channels
);
2000 if (err
>= 0 && spec
->need_dac_fix
)
2001 spec
->multiout
.num_dacs
= spec
->multiout
.max_channels
/ 2;
2006 static struct snd_kcontrol_new ad1988_6stack_mixers1
[] = {
2007 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2008 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2009 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2010 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2011 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2015 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2
[] = {
2016 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2017 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT
),
2018 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2019 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT
),
2020 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT
),
2024 static struct snd_kcontrol_new ad1988_6stack_mixers2
[] = {
2025 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2026 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT
),
2027 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT
),
2028 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT
),
2029 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT
),
2030 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2031 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2033 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2034 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2035 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2036 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2037 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2038 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2039 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2040 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2042 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2043 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2045 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
2046 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT
),
2052 static struct snd_kcontrol_new ad1988_3stack_mixers1
[] = {
2053 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2054 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2055 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
2056 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
2060 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2
[] = {
2061 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2062 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT
),
2063 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT
),
2064 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT
),
2068 static struct snd_kcontrol_new ad1988_3stack_mixers2
[] = {
2069 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT
),
2070 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT
),
2071 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT
),
2072 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT
),
2073 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT
),
2074 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2076 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2077 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2078 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2079 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2080 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2081 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2082 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT
),
2083 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT
),
2085 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2086 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2088 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
2089 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT
),
2091 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2092 .name
= "Channel Mode",
2093 .info
= ad198x_ch_mode_info
,
2094 .get
= ad198x_ch_mode_get
,
2095 .put
= ad198x_ch_mode_put
,
2102 static struct snd_kcontrol_new ad1988_laptop_mixers
[] = {
2103 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
2104 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT
),
2105 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT
),
2107 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT
),
2108 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT
),
2109 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT
),
2110 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT
),
2111 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT
),
2112 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT
),
2114 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
2115 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
2117 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
2120 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2121 .name
= "External Amplifier",
2122 .info
= ad198x_eapd_info
,
2123 .get
= ad198x_eapd_get
,
2124 .put
= ad198x_eapd_put
,
2125 .private_value
= 0x12 | (1 << 8), /* port-D, inversed */
2132 static struct snd_kcontrol_new ad1988_capture_mixers
[] = {
2133 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
2134 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
2135 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
2136 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
2137 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT
),
2138 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT
),
2140 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2141 /* The multiple "Capture Source" controls confuse alsamixer
2142 * So call somewhat different..
2144 /* .name = "Capture Source", */
2145 .name
= "Input Source",
2147 .info
= ad198x_mux_enum_info
,
2148 .get
= ad198x_mux_enum_get
,
2149 .put
= ad198x_mux_enum_put
,
2154 static int ad1988_spdif_playback_source_info(struct snd_kcontrol
*kcontrol
,
2155 struct snd_ctl_elem_info
*uinfo
)
2157 static char *texts
[] = {
2158 "PCM", "ADC1", "ADC2", "ADC3"
2160 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
2162 uinfo
->value
.enumerated
.items
= 4;
2163 if (uinfo
->value
.enumerated
.item
>= 4)
2164 uinfo
->value
.enumerated
.item
= 3;
2165 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
2169 static int ad1988_spdif_playback_source_get(struct snd_kcontrol
*kcontrol
,
2170 struct snd_ctl_elem_value
*ucontrol
)
2172 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2175 sel
= snd_hda_codec_read(codec
, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE
,
2178 ucontrol
->value
.enumerated
.item
[0] = 0;
2180 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2181 AC_VERB_GET_CONNECT_SEL
, 0);
2186 ucontrol
->value
.enumerated
.item
[0] = sel
;
2191 static int ad1988_spdif_playback_source_put(struct snd_kcontrol
*kcontrol
,
2192 struct snd_ctl_elem_value
*ucontrol
)
2194 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2195 unsigned int val
, sel
;
2198 val
= ucontrol
->value
.enumerated
.item
[0];
2202 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2203 AC_VERB_GET_AMP_GAIN_MUTE
,
2205 change
= sel
& 0x80;
2207 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2208 AC_VERB_SET_AMP_GAIN_MUTE
,
2210 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2211 AC_VERB_SET_AMP_GAIN_MUTE
,
2215 sel
= snd_hda_codec_read(codec
, 0x1d, 0,
2216 AC_VERB_GET_AMP_GAIN_MUTE
,
2217 AC_AMP_GET_INPUT
| 0x01);
2218 change
= sel
& 0x80;
2220 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2221 AC_VERB_SET_AMP_GAIN_MUTE
,
2223 snd_hda_codec_write_cache(codec
, 0x1d, 0,
2224 AC_VERB_SET_AMP_GAIN_MUTE
,
2227 sel
= snd_hda_codec_read(codec
, 0x0b, 0,
2228 AC_VERB_GET_CONNECT_SEL
, 0) + 1;
2229 change
|= sel
!= val
;
2231 snd_hda_codec_write_cache(codec
, 0x0b, 0,
2232 AC_VERB_SET_CONNECT_SEL
,
2238 static struct snd_kcontrol_new ad1988_spdif_out_mixers
[] = {
2239 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2241 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2242 .name
= "IEC958 Playback Source",
2243 .info
= ad1988_spdif_playback_source_info
,
2244 .get
= ad1988_spdif_playback_source_get
,
2245 .put
= ad1988_spdif_playback_source_put
,
2250 static struct snd_kcontrol_new ad1988_spdif_in_mixers
[] = {
2251 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT
),
2255 static struct snd_kcontrol_new ad1989_spdif_out_mixers
[] = {
2256 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
2257 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT
),
2262 * initialization verbs
2266 * for 6-stack (+dig)
2268 static struct hda_verb ad1988_6stack_init_verbs
[] = {
2269 /* Front, Surround, CLFE, side DAC; unmute as default */
2270 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2271 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2272 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2273 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2274 /* Port-A front headphon path */
2275 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2276 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2277 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2278 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2279 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2280 /* Port-D line-out path */
2281 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2282 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2283 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2284 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2285 /* Port-F surround path */
2286 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2287 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2288 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2289 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2290 /* Port-G CLFE path */
2291 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2292 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2293 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2294 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2295 /* Port-H side path */
2296 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2297 {0x28, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2298 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2299 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2301 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2302 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2303 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2304 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2305 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2306 /* Port-B front mic-in path */
2307 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2308 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2309 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2310 /* Port-C line-in path */
2311 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2312 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2313 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2314 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2315 /* Port-E mic-in path */
2316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2317 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2318 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2319 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2320 /* Analog CD Input */
2321 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2322 /* Analog Mix output amp */
2323 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2328 static struct hda_verb ad1988_capture_init_verbs
[] = {
2329 /* mute analog mix */
2330 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2331 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2332 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2333 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2334 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2335 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2336 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2337 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2338 /* select ADCs - front-mic */
2339 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2340 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2341 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2346 static struct hda_verb ad1988_spdif_init_verbs
[] = {
2348 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
2349 {0x0b, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* ADC1 */
2350 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2351 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2353 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2358 /* AD1989 has no ADC -> SPDIF route */
2359 static struct hda_verb ad1989_spdif_init_verbs
[] = {
2360 /* SPDIF-1 out pin */
2361 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2362 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2363 /* SPDIF-2/HDMI out pin */
2364 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2365 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
2370 * verbs for 3stack (+dig)
2372 static struct hda_verb ad1988_3stack_ch2_init
[] = {
2373 /* set port-C to line-in */
2374 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2375 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2376 /* set port-E to mic-in */
2377 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2378 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2382 static struct hda_verb ad1988_3stack_ch6_init
[] = {
2383 /* set port-C to surround out */
2384 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2385 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2386 /* set port-E to CLFE out */
2387 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2388 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2392 static struct hda_channel_mode ad1988_3stack_modes
[2] = {
2393 { 2, ad1988_3stack_ch2_init
},
2394 { 6, ad1988_3stack_ch6_init
},
2397 static struct hda_verb ad1988_3stack_init_verbs
[] = {
2398 /* Front, Surround, CLFE, side DAC; unmute as default */
2399 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2400 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2401 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2402 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2403 /* Port-A front headphon path */
2404 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2405 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2406 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2407 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2408 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2409 /* Port-D line-out path */
2410 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2411 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2412 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2413 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2415 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2416 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2417 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2418 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2419 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2420 /* Port-B front mic-in path */
2421 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2422 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2423 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2424 /* Port-C line-in/surround path - 6ch mode as default */
2425 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2426 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2427 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2428 {0x31, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* output sel: DAC 0x05 */
2429 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2430 /* Port-E mic-in/CLFE path - 6ch mode as default */
2431 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2432 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2433 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2434 {0x32, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* output sel: DAC 0x0a */
2435 {0x34, AC_VERB_SET_CONNECT_SEL
, 0x0},
2436 /* mute analog mix */
2437 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2438 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2440 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2441 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2442 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2443 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2444 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2445 /* select ADCs - front-mic */
2446 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2447 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2448 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2449 /* Analog Mix output amp */
2450 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2455 * verbs for laptop mode (+dig)
2457 static struct hda_verb ad1988_laptop_hp_on
[] = {
2458 /* unmute port-A and mute port-D */
2459 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2460 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2463 static struct hda_verb ad1988_laptop_hp_off
[] = {
2464 /* mute port-A and unmute port-D */
2465 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2466 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2470 #define AD1988_HP_EVENT 0x01
2472 static struct hda_verb ad1988_laptop_init_verbs
[] = {
2473 /* Front, Surround, CLFE, side DAC; unmute as default */
2474 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2475 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2476 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2477 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2478 /* Port-A front headphon path */
2479 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* DAC1:04h */
2480 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2481 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2482 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2483 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2484 /* unsolicited event for pin-sense */
2485 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1988_HP_EVENT
},
2486 /* Port-D line-out path + EAPD */
2487 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2488 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2489 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2490 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2491 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x00}, /* EAPD-off */
2493 {0x36, AC_VERB_SET_CONNECT_SEL
, 0x1}, /* DAC1:04h */
2494 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2495 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2496 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2497 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb01f}, /* unmute, 0dB */
2498 /* Port-B mic-in path */
2499 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2500 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2501 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2502 /* Port-C docking station - try to output */
2503 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2504 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2505 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2506 {0x33, AC_VERB_SET_CONNECT_SEL
, 0x0},
2507 /* mute analog mix */
2508 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2509 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2510 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2511 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2512 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2513 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
2514 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
2515 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
2516 /* select ADCs - mic */
2517 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x1},
2518 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x1},
2519 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
2520 /* Analog Mix output amp */
2521 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
2525 static void ad1988_laptop_unsol_event(struct hda_codec
*codec
, unsigned int res
)
2527 if ((res
>> 26) != AD1988_HP_EVENT
)
2529 if (snd_hda_codec_read(codec
, 0x11, 0, AC_VERB_GET_PIN_SENSE
, 0) & (1 << 31))
2530 snd_hda_sequence_write(codec
, ad1988_laptop_hp_on
);
2532 snd_hda_sequence_write(codec
, ad1988_laptop_hp_off
);
2535 #ifdef CONFIG_SND_HDA_POWER_SAVE
2536 static struct hda_amp_list ad1988_loopbacks
[] = {
2537 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
2538 { 0x20, HDA_INPUT
, 1 }, /* Line */
2539 { 0x20, HDA_INPUT
, 4 }, /* Mic */
2540 { 0x20, HDA_INPUT
, 6 }, /* CD */
2546 * Automatic parse of I/O pins from the BIOS configuration
2554 static struct snd_kcontrol_new ad1988_control_templates
[] = {
2555 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
2556 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
2557 HDA_BIND_MUTE(NULL
, 0, 0, 0),
2560 /* add dynamic controls */
2561 static int add_control(struct ad198x_spec
*spec
, int type
, const char *name
,
2564 struct snd_kcontrol_new
*knew
;
2566 snd_array_init(&spec
->kctls
, sizeof(*knew
), 32);
2567 knew
= snd_array_new(&spec
->kctls
);
2570 *knew
= ad1988_control_templates
[type
];
2571 knew
->name
= kstrdup(name
, GFP_KERNEL
);
2574 if (get_amp_nid_(val
))
2575 knew
->subdevice
= (1<<31)|get_amp_nid_(val
);
2576 knew
->private_value
= val
;
2580 #define AD1988_PIN_CD_NID 0x18
2581 #define AD1988_PIN_BEEP_NID 0x10
2583 static hda_nid_t ad1988_mixer_nids
[8] = {
2584 /* A B C D E F G H */
2585 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2588 static inline hda_nid_t
ad1988_idx_to_dac(struct hda_codec
*codec
, int idx
)
2590 static hda_nid_t idx_to_dac
[8] = {
2591 /* A B C D E F G H */
2592 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2594 static hda_nid_t idx_to_dac_rev2
[8] = {
2595 /* A B C D E F G H */
2596 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2599 return idx_to_dac_rev2
[idx
];
2601 return idx_to_dac
[idx
];
2604 static hda_nid_t ad1988_boost_nids
[8] = {
2605 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2608 static int ad1988_pin_idx(hda_nid_t nid
)
2610 static hda_nid_t ad1988_io_pins
[8] = {
2611 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2614 for (i
= 0; i
< ARRAY_SIZE(ad1988_io_pins
); i
++)
2615 if (ad1988_io_pins
[i
] == nid
)
2617 return 0; /* should be -1 */
2620 static int ad1988_pin_to_loopback_idx(hda_nid_t nid
)
2622 static int loopback_idx
[8] = {
2623 2, 0, 1, 3, 4, 5, 1, 4
2626 case AD1988_PIN_CD_NID
:
2629 return loopback_idx
[ad1988_pin_idx(nid
)];
2633 static int ad1988_pin_to_adc_idx(hda_nid_t nid
)
2635 static int adc_idx
[8] = {
2636 0, 1, 2, 8, 4, 3, 6, 7
2639 case AD1988_PIN_CD_NID
:
2642 return adc_idx
[ad1988_pin_idx(nid
)];
2646 /* fill in the dac_nids table from the parsed pin configuration */
2647 static int ad1988_auto_fill_dac_nids(struct hda_codec
*codec
,
2648 const struct auto_pin_cfg
*cfg
)
2650 struct ad198x_spec
*spec
= codec
->spec
;
2653 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2655 /* check the pins hardwired to audio widget */
2656 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2657 idx
= ad1988_pin_idx(cfg
->line_out_pins
[i
]);
2658 spec
->multiout
.dac_nids
[i
] = ad1988_idx_to_dac(codec
, idx
);
2660 spec
->multiout
.num_dacs
= cfg
->line_outs
;
2664 /* add playback controls from the parsed DAC table */
2665 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec
*spec
,
2666 const struct auto_pin_cfg
*cfg
)
2669 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
2673 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2674 hda_nid_t dac
= spec
->multiout
.dac_nids
[i
];
2677 nid
= ad1988_mixer_nids
[ad1988_pin_idx(cfg
->line_out_pins
[i
])];
2680 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2681 "Center Playback Volume",
2682 HDA_COMPOSE_AMP_VAL(dac
, 1, 0, HDA_OUTPUT
));
2685 err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2686 "LFE Playback Volume",
2687 HDA_COMPOSE_AMP_VAL(dac
, 2, 0, HDA_OUTPUT
));
2690 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
2691 "Center Playback Switch",
2692 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
));
2695 err
= add_control(spec
, AD_CTL_BIND_MUTE
,
2696 "LFE Playback Switch",
2697 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
));
2701 sprintf(name
, "%s Playback Volume", chname
[i
]);
2702 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2703 HDA_COMPOSE_AMP_VAL(dac
, 3, 0, HDA_OUTPUT
));
2706 sprintf(name
, "%s Playback Switch", chname
[i
]);
2707 err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
2708 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
));
2716 /* add playback controls for speaker and HP outputs */
2717 static int ad1988_auto_create_extra_out(struct hda_codec
*codec
, hda_nid_t pin
,
2720 struct ad198x_spec
*spec
= codec
->spec
;
2728 idx
= ad1988_pin_idx(pin
);
2729 nid
= ad1988_idx_to_dac(codec
, idx
);
2730 /* check whether the corresponding DAC was already taken */
2731 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
2732 hda_nid_t pin
= spec
->autocfg
.line_out_pins
[i
];
2733 hda_nid_t dac
= ad1988_idx_to_dac(codec
, ad1988_pin_idx(pin
));
2737 if (i
>= spec
->autocfg
.line_outs
) {
2738 /* specify the DAC as the extra output */
2739 if (!spec
->multiout
.hp_nid
)
2740 spec
->multiout
.hp_nid
= nid
;
2742 spec
->multiout
.extra_out_nid
[0] = nid
;
2743 /* control HP volume/switch on the output mixer amp */
2744 sprintf(name
, "%s Playback Volume", pfx
);
2745 err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2746 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
2750 nid
= ad1988_mixer_nids
[idx
];
2751 sprintf(name
, "%s Playback Switch", pfx
);
2752 if ((err
= add_control(spec
, AD_CTL_BIND_MUTE
, name
,
2753 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2758 /* create input playback/capture controls for the given pin */
2759 static int new_analog_input(struct ad198x_spec
*spec
, hda_nid_t pin
,
2760 const char *ctlname
, int boost
)
2765 sprintf(name
, "%s Playback Volume", ctlname
);
2766 idx
= ad1988_pin_to_loopback_idx(pin
);
2767 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2768 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
2770 sprintf(name
, "%s Playback Switch", ctlname
);
2771 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
, name
,
2772 HDA_COMPOSE_AMP_VAL(0x20, 3, idx
, HDA_INPUT
))) < 0)
2776 idx
= ad1988_pin_idx(pin
);
2777 bnid
= ad1988_boost_nids
[idx
];
2779 sprintf(name
, "%s Boost", ctlname
);
2780 return add_control(spec
, AD_CTL_WIDGET_VOL
, name
,
2781 HDA_COMPOSE_AMP_VAL(bnid
, 3, idx
, HDA_OUTPUT
));
2788 /* create playback/capture controls for input pins */
2789 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec
*spec
,
2790 const struct auto_pin_cfg
*cfg
)
2792 struct hda_input_mux
*imux
= &spec
->private_imux
;
2795 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2796 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
2797 auto_pin_cfg_labels
[i
],
2798 i
<= AUTO_PIN_FRONT_MIC
);
2801 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
2802 imux
->items
[imux
->num_items
].index
= ad1988_pin_to_adc_idx(cfg
->input_pins
[i
]);
2805 imux
->items
[imux
->num_items
].label
= "Mix";
2806 imux
->items
[imux
->num_items
].index
= 9;
2809 if ((err
= add_control(spec
, AD_CTL_WIDGET_VOL
,
2810 "Analog Mix Playback Volume",
2811 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
2813 if ((err
= add_control(spec
, AD_CTL_WIDGET_MUTE
,
2814 "Analog Mix Playback Switch",
2815 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT
))) < 0)
2821 static void ad1988_auto_set_output_and_unmute(struct hda_codec
*codec
,
2822 hda_nid_t nid
, int pin_type
,
2826 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
2827 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
2829 case 0x11: /* port-A - DAC 04 */
2830 snd_hda_codec_write(codec
, 0x37, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
2832 case 0x14: /* port-B - DAC 06 */
2833 snd_hda_codec_write(codec
, 0x30, 0, AC_VERB_SET_CONNECT_SEL
, 0x02);
2835 case 0x15: /* port-C - DAC 05 */
2836 snd_hda_codec_write(codec
, 0x31, 0, AC_VERB_SET_CONNECT_SEL
, 0x00);
2838 case 0x17: /* port-E - DAC 0a */
2839 snd_hda_codec_write(codec
, 0x32, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
2841 case 0x13: /* mono - DAC 04 */
2842 snd_hda_codec_write(codec
, 0x36, 0, AC_VERB_SET_CONNECT_SEL
, 0x01);
2847 static void ad1988_auto_init_multi_out(struct hda_codec
*codec
)
2849 struct ad198x_spec
*spec
= codec
->spec
;
2852 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
2853 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
2854 ad1988_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
2858 static void ad1988_auto_init_extra_out(struct hda_codec
*codec
)
2860 struct ad198x_spec
*spec
= codec
->spec
;
2863 pin
= spec
->autocfg
.speaker_pins
[0];
2864 if (pin
) /* connect to front */
2865 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
2866 pin
= spec
->autocfg
.hp_pins
[0];
2867 if (pin
) /* connect to front */
2868 ad1988_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
2871 static void ad1988_auto_init_analog_input(struct hda_codec
*codec
)
2873 struct ad198x_spec
*spec
= codec
->spec
;
2876 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2877 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
2881 case 0x15: /* port-C */
2882 snd_hda_codec_write(codec
, 0x33, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
2884 case 0x17: /* port-E */
2885 snd_hda_codec_write(codec
, 0x34, 0, AC_VERB_SET_CONNECT_SEL
, 0x0);
2888 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
2889 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
2890 if (nid
!= AD1988_PIN_CD_NID
)
2891 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
2893 idx
= ad1988_pin_idx(nid
);
2894 if (ad1988_boost_nids
[idx
])
2895 snd_hda_codec_write(codec
, ad1988_boost_nids
[idx
], 0,
2896 AC_VERB_SET_AMP_GAIN_MUTE
,
2901 /* parse the BIOS configuration and set up the alc_spec */
2902 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2903 static int ad1988_parse_auto_config(struct hda_codec
*codec
)
2905 struct ad198x_spec
*spec
= codec
->spec
;
2908 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
2910 if ((err
= ad1988_auto_fill_dac_nids(codec
, &spec
->autocfg
)) < 0)
2912 if (! spec
->autocfg
.line_outs
)
2913 return 0; /* can't find valid BIOS pin config */
2914 if ((err
= ad1988_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
2915 (err
= ad1988_auto_create_extra_out(codec
,
2916 spec
->autocfg
.speaker_pins
[0],
2918 (err
= ad1988_auto_create_extra_out(codec
, spec
->autocfg
.hp_pins
[0],
2919 "Headphone")) < 0 ||
2920 (err
= ad1988_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
2923 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
2925 if (spec
->autocfg
.dig_outs
)
2926 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
2927 if (spec
->autocfg
.dig_in_pin
)
2928 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
2930 if (spec
->kctls
.list
)
2931 spec
->mixers
[spec
->num_mixers
++] = spec
->kctls
.list
;
2933 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_6stack_init_verbs
;
2935 spec
->input_mux
= &spec
->private_imux
;
2940 /* init callback for auto-configuration model -- overriding the default init */
2941 static int ad1988_auto_init(struct hda_codec
*codec
)
2944 ad1988_auto_init_multi_out(codec
);
2945 ad1988_auto_init_extra_out(codec
);
2946 ad1988_auto_init_analog_input(codec
);
2954 static const char *ad1988_models
[AD1988_MODEL_LAST
] = {
2955 [AD1988_6STACK
] = "6stack",
2956 [AD1988_6STACK_DIG
] = "6stack-dig",
2957 [AD1988_3STACK
] = "3stack",
2958 [AD1988_3STACK_DIG
] = "3stack-dig",
2959 [AD1988_LAPTOP
] = "laptop",
2960 [AD1988_LAPTOP_DIG
] = "laptop-dig",
2961 [AD1988_AUTO
] = "auto",
2964 static struct snd_pci_quirk ad1988_cfg_tbl
[] = {
2965 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG
),
2966 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG
),
2967 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG
),
2968 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG
),
2972 static int patch_ad1988(struct hda_codec
*codec
)
2974 struct ad198x_spec
*spec
;
2975 int err
, board_config
;
2977 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
2984 snd_printk(KERN_INFO
"patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2986 board_config
= snd_hda_check_board_config(codec
, AD1988_MODEL_LAST
,
2987 ad1988_models
, ad1988_cfg_tbl
);
2988 if (board_config
< 0) {
2989 printk(KERN_INFO
"hda_codec: %s: BIOS auto-probing.\n",
2991 board_config
= AD1988_AUTO
;
2994 if (board_config
== AD1988_AUTO
) {
2995 /* automatic parse from the BIOS config */
2996 err
= ad1988_parse_auto_config(codec
);
3001 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3002 board_config
= AD1988_6STACK
;
3006 err
= snd_hda_attach_beep_device(codec
, 0x10);
3011 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3013 switch (board_config
) {
3015 case AD1988_6STACK_DIG
:
3016 spec
->multiout
.max_channels
= 8;
3017 spec
->multiout
.num_dacs
= 4;
3019 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids_rev2
;
3021 spec
->multiout
.dac_nids
= ad1988_6stack_dac_nids
;
3022 spec
->input_mux
= &ad1988_6stack_capture_source
;
3023 spec
->num_mixers
= 2;
3025 spec
->mixers
[0] = ad1988_6stack_mixers1_rev2
;
3027 spec
->mixers
[0] = ad1988_6stack_mixers1
;
3028 spec
->mixers
[1] = ad1988_6stack_mixers2
;
3029 spec
->num_init_verbs
= 1;
3030 spec
->init_verbs
[0] = ad1988_6stack_init_verbs
;
3031 if (board_config
== AD1988_6STACK_DIG
) {
3032 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3033 spec
->dig_in_nid
= AD1988_SPDIF_IN
;
3037 case AD1988_3STACK_DIG
:
3038 spec
->multiout
.max_channels
= 6;
3039 spec
->multiout
.num_dacs
= 3;
3041 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids_rev2
;
3043 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3044 spec
->input_mux
= &ad1988_6stack_capture_source
;
3045 spec
->channel_mode
= ad1988_3stack_modes
;
3046 spec
->num_channel_mode
= ARRAY_SIZE(ad1988_3stack_modes
);
3047 spec
->num_mixers
= 2;
3049 spec
->mixers
[0] = ad1988_3stack_mixers1_rev2
;
3051 spec
->mixers
[0] = ad1988_3stack_mixers1
;
3052 spec
->mixers
[1] = ad1988_3stack_mixers2
;
3053 spec
->num_init_verbs
= 1;
3054 spec
->init_verbs
[0] = ad1988_3stack_init_verbs
;
3055 if (board_config
== AD1988_3STACK_DIG
)
3056 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3059 case AD1988_LAPTOP_DIG
:
3060 spec
->multiout
.max_channels
= 2;
3061 spec
->multiout
.num_dacs
= 1;
3062 spec
->multiout
.dac_nids
= ad1988_3stack_dac_nids
;
3063 spec
->input_mux
= &ad1988_laptop_capture_source
;
3064 spec
->num_mixers
= 1;
3065 spec
->mixers
[0] = ad1988_laptop_mixers
;
3066 spec
->num_init_verbs
= 1;
3067 spec
->init_verbs
[0] = ad1988_laptop_init_verbs
;
3068 if (board_config
== AD1988_LAPTOP_DIG
)
3069 spec
->multiout
.dig_out_nid
= AD1988_SPDIF_OUT
;
3073 spec
->num_adc_nids
= ARRAY_SIZE(ad1988_adc_nids
);
3074 spec
->adc_nids
= ad1988_adc_nids
;
3075 spec
->capsrc_nids
= ad1988_capsrc_nids
;
3076 spec
->mixers
[spec
->num_mixers
++] = ad1988_capture_mixers
;
3077 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1988_capture_init_verbs
;
3078 if (spec
->multiout
.dig_out_nid
) {
3079 if (codec
->vendor_id
>= 0x11d4989a) {
3080 spec
->mixers
[spec
->num_mixers
++] =
3081 ad1989_spdif_out_mixers
;
3082 spec
->init_verbs
[spec
->num_init_verbs
++] =
3083 ad1989_spdif_init_verbs
;
3084 codec
->slave_dig_outs
= ad1989b_slave_dig_outs
;
3086 spec
->mixers
[spec
->num_mixers
++] =
3087 ad1988_spdif_out_mixers
;
3088 spec
->init_verbs
[spec
->num_init_verbs
++] =
3089 ad1988_spdif_init_verbs
;
3092 if (spec
->dig_in_nid
&& codec
->vendor_id
< 0x11d4989a)
3093 spec
->mixers
[spec
->num_mixers
++] = ad1988_spdif_in_mixers
;
3095 codec
->patch_ops
= ad198x_patch_ops
;
3096 switch (board_config
) {
3098 codec
->patch_ops
.init
= ad1988_auto_init
;
3101 case AD1988_LAPTOP_DIG
:
3102 codec
->patch_ops
.unsol_event
= ad1988_laptop_unsol_event
;
3105 #ifdef CONFIG_SND_HDA_POWER_SAVE
3106 spec
->loopback
.amplist
= ad1988_loopbacks
;
3108 spec
->vmaster_nid
= 0x04;
3117 * port-B - front line/mic-in
3118 * port-E - aux in/out
3119 * port-F - aux in/out
3120 * port-C - rear line/mic-in
3121 * port-D - rear line/hp-out
3122 * port-A - front line/hp-out
3124 * AD1984 = AD1884 + two digital mic-ins
3127 * For simplicity, we share the single DAC for both HP and line-outs
3128 * right now. The inidividual playbacks could be easily implemented,
3129 * but no build-up framework is given, so far.
3132 static hda_nid_t ad1884_dac_nids
[1] = {
3136 static hda_nid_t ad1884_adc_nids
[2] = {
3140 static hda_nid_t ad1884_capsrc_nids
[2] = {
3144 #define AD1884_SPDIF_OUT 0x02
3146 static struct hda_input_mux ad1884_capture_source
= {
3149 { "Front Mic", 0x0 },
3156 static struct snd_kcontrol_new ad1884_base_mixers
[] = {
3157 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3158 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3159 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3160 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3161 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3162 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3163 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3164 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3165 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3166 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3167 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3168 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3169 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT
),
3170 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT
),
3171 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3172 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3173 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3174 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3176 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3177 /* The multiple "Capture Source" controls confuse alsamixer
3178 * So call somewhat different..
3180 /* .name = "Capture Source", */
3181 .name
= "Input Source",
3183 .info
= ad198x_mux_enum_info
,
3184 .get
= ad198x_mux_enum_get
,
3185 .put
= ad198x_mux_enum_put
,
3187 /* SPDIF controls */
3188 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3190 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3191 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3192 /* identical with ad1983 */
3193 .info
= ad1983_spdif_route_info
,
3194 .get
= ad1983_spdif_route_get
,
3195 .put
= ad1983_spdif_route_put
,
3200 static struct snd_kcontrol_new ad1984_dmic_mixers
[] = {
3201 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT
),
3202 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT
),
3203 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3205 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3211 * initialization verbs
3213 static struct hda_verb ad1884_init_verbs
[] = {
3214 /* DACs; mute as default */
3215 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3216 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3217 /* Port-A (HP) mixer */
3218 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3219 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3221 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3222 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3223 /* HP selector - select DAC2 */
3224 {0x22, AC_VERB_SET_CONNECT_SEL
, 0x1},
3225 /* Port-D (Line-out) mixer */
3226 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3227 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3229 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3230 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3231 /* Mono-out mixer */
3232 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3233 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3235 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3236 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3238 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x1},
3239 /* Port-B (front mic) pin */
3240 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3241 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3242 /* Port-C (rear mic) pin */
3243 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3244 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3245 /* Analog mixer; mute as default */
3246 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3247 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3248 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3249 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3250 /* Analog Mix output amp */
3251 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
3252 /* SPDIF output selector */
3253 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
3254 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
3258 #ifdef CONFIG_SND_HDA_POWER_SAVE
3259 static struct hda_amp_list ad1884_loopbacks
[] = {
3260 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
3261 { 0x20, HDA_INPUT
, 1 }, /* Mic */
3262 { 0x20, HDA_INPUT
, 2 }, /* CD */
3263 { 0x20, HDA_INPUT
, 4 }, /* Docking */
3268 static const char *ad1884_slave_vols
[] = {
3269 "PCM Playback Volume",
3270 "Mic Playback Volume",
3271 "Mono Playback Volume",
3272 "Front Mic Playback Volume",
3273 "Mic Playback Volume",
3274 "CD Playback Volume",
3275 "Internal Mic Playback Volume",
3276 "Docking Mic Playback Volume",
3277 /* "Beep Playback Volume", */
3278 "IEC958 Playback Volume",
3282 static int patch_ad1884(struct hda_codec
*codec
)
3284 struct ad198x_spec
*spec
;
3287 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3293 err
= snd_hda_attach_beep_device(codec
, 0x10);
3298 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
3300 spec
->multiout
.max_channels
= 2;
3301 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884_dac_nids
);
3302 spec
->multiout
.dac_nids
= ad1884_dac_nids
;
3303 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3304 spec
->num_adc_nids
= ARRAY_SIZE(ad1884_adc_nids
);
3305 spec
->adc_nids
= ad1884_adc_nids
;
3306 spec
->capsrc_nids
= ad1884_capsrc_nids
;
3307 spec
->input_mux
= &ad1884_capture_source
;
3308 spec
->num_mixers
= 1;
3309 spec
->mixers
[0] = ad1884_base_mixers
;
3310 spec
->num_init_verbs
= 1;
3311 spec
->init_verbs
[0] = ad1884_init_verbs
;
3312 spec
->spdif_route
= 0;
3313 #ifdef CONFIG_SND_HDA_POWER_SAVE
3314 spec
->loopback
.amplist
= ad1884_loopbacks
;
3316 spec
->vmaster_nid
= 0x04;
3317 /* we need to cover all playback volumes */
3318 spec
->slave_vols
= ad1884_slave_vols
;
3320 codec
->patch_ops
= ad198x_patch_ops
;
3326 * Lenovo Thinkpad T61/X61
3328 static struct hda_input_mux ad1984_thinkpad_capture_source
= {
3332 { "Internal Mic", 0x1 },
3334 { "Docking-Station", 0x4 },
3340 * Dell Precision T3400
3342 static struct hda_input_mux ad1984_dell_desktop_capture_source
= {
3345 { "Front Mic", 0x0 },
3352 static struct snd_kcontrol_new ad1984_thinkpad_mixers
[] = {
3353 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3354 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3355 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3356 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3357 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3358 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3359 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3360 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3361 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3362 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3363 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT
),
3364 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT
),
3365 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT
),
3366 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3367 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3368 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3369 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3371 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3372 /* The multiple "Capture Source" controls confuse alsamixer
3373 * So call somewhat different..
3375 /* .name = "Capture Source", */
3376 .name
= "Input Source",
3378 .info
= ad198x_mux_enum_info
,
3379 .get
= ad198x_mux_enum_get
,
3380 .put
= ad198x_mux_enum_put
,
3382 /* SPDIF controls */
3383 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3385 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3386 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3387 /* identical with ad1983 */
3388 .info
= ad1983_spdif_route_info
,
3389 .get
= ad1983_spdif_route_get
,
3390 .put
= ad1983_spdif_route_put
,
3395 /* additional verbs */
3396 static struct hda_verb ad1984_thinkpad_init_verbs
[] = {
3397 /* Port-E (docking station mic) pin */
3398 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3399 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3400 /* docking mic boost */
3401 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3402 /* Analog mixer - docking mic; mute as default */
3403 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3404 /* enable EAPD bit */
3405 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
3410 * Dell Precision T3400
3412 static struct snd_kcontrol_new ad1984_dell_desktop_mixers
[] = {
3413 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
3414 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3415 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3416 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3417 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3418 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3419 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3420 HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT
),
3421 HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT
),
3422 HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT
),
3423 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT
),
3424 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3425 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3426 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3427 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3429 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3430 /* The multiple "Capture Source" controls confuse alsamixer
3431 * So call somewhat different..
3433 /* .name = "Capture Source", */
3434 .name
= "Input Source",
3436 .info
= ad198x_mux_enum_info
,
3437 .get
= ad198x_mux_enum_get
,
3438 .put
= ad198x_mux_enum_put
,
3443 /* Digial MIC ADC NID 0x05 + 0x06 */
3444 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream
*hinfo
,
3445 struct hda_codec
*codec
,
3446 unsigned int stream_tag
,
3447 unsigned int format
,
3448 struct snd_pcm_substream
*substream
)
3450 snd_hda_codec_setup_stream(codec
, 0x05 + substream
->number
,
3451 stream_tag
, 0, format
);
3455 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream
*hinfo
,
3456 struct hda_codec
*codec
,
3457 struct snd_pcm_substream
*substream
)
3459 snd_hda_codec_cleanup_stream(codec
, 0x05 + substream
->number
);
3463 static struct hda_pcm_stream ad1984_pcm_dmic_capture
= {
3469 .prepare
= ad1984_pcm_dmic_prepare
,
3470 .cleanup
= ad1984_pcm_dmic_cleanup
3474 static int ad1984_build_pcms(struct hda_codec
*codec
)
3476 struct ad198x_spec
*spec
= codec
->spec
;
3477 struct hda_pcm
*info
;
3480 err
= ad198x_build_pcms(codec
);
3484 info
= spec
->pcm_rec
+ codec
->num_pcms
;
3486 info
->name
= "AD1984 Digital Mic";
3487 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ad1984_pcm_dmic_capture
;
3495 AD1984_DELL_DESKTOP
,
3499 static const char *ad1984_models
[AD1984_MODELS
] = {
3500 [AD1984_BASIC
] = "basic",
3501 [AD1984_THINKPAD
] = "thinkpad",
3502 [AD1984_DELL_DESKTOP
] = "dell_desktop",
3505 static struct snd_pci_quirk ad1984_cfg_tbl
[] = {
3506 /* Lenovo Thinkpad T61/X61 */
3507 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD
),
3508 SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP
),
3512 static int patch_ad1984(struct hda_codec
*codec
)
3514 struct ad198x_spec
*spec
;
3515 int board_config
, err
;
3517 err
= patch_ad1884(codec
);
3521 board_config
= snd_hda_check_board_config(codec
, AD1984_MODELS
,
3522 ad1984_models
, ad1984_cfg_tbl
);
3523 switch (board_config
) {
3525 /* additional digital mics */
3526 spec
->mixers
[spec
->num_mixers
++] = ad1984_dmic_mixers
;
3527 codec
->patch_ops
.build_pcms
= ad1984_build_pcms
;
3529 case AD1984_THINKPAD
:
3530 spec
->multiout
.dig_out_nid
= AD1884_SPDIF_OUT
;
3531 spec
->input_mux
= &ad1984_thinkpad_capture_source
;
3532 spec
->mixers
[0] = ad1984_thinkpad_mixers
;
3533 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1984_thinkpad_init_verbs
;
3535 case AD1984_DELL_DESKTOP
:
3536 spec
->multiout
.dig_out_nid
= 0;
3537 spec
->input_mux
= &ad1984_dell_desktop_capture_source
;
3538 spec
->mixers
[0] = ad1984_dell_desktop_mixers
;
3546 * AD1883 / AD1884A / AD1984A / AD1984B
3548 * port-B (0x14) - front mic-in
3549 * port-E (0x1c) - rear mic-in
3550 * port-F (0x16) - CD / ext out
3551 * port-C (0x15) - rear line-in
3552 * port-D (0x12) - rear line-out
3553 * port-A (0x11) - front hp-out
3555 * AD1984A = AD1884A + digital-mic
3556 * AD1883 = equivalent with AD1984A
3557 * AD1984B = AD1984A + extra SPDIF-out
3560 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3563 static hda_nid_t ad1884a_dac_nids
[1] = {
3567 #define ad1884a_adc_nids ad1884_adc_nids
3568 #define ad1884a_capsrc_nids ad1884_capsrc_nids
3570 #define AD1884A_SPDIF_OUT 0x02
3572 static struct hda_input_mux ad1884a_capture_source
= {
3575 { "Front Mic", 0x0 },
3583 static struct snd_kcontrol_new ad1884a_base_mixers
[] = {
3584 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3585 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
3586 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
3587 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3588 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
3589 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
3590 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3591 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3592 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3593 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3594 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
3595 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
3596 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3597 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3598 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT
),
3599 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT
),
3600 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT
),
3601 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT
),
3602 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT
),
3603 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3604 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3605 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
3606 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
3608 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3609 /* The multiple "Capture Source" controls confuse alsamixer
3610 * So call somewhat different..
3612 /* .name = "Capture Source", */
3613 .name
= "Input Source",
3615 .info
= ad198x_mux_enum_info
,
3616 .get
= ad198x_mux_enum_get
,
3617 .put
= ad198x_mux_enum_put
,
3619 /* SPDIF controls */
3620 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
3622 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3623 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
3624 /* identical with ad1983 */
3625 .info
= ad1983_spdif_route_info
,
3626 .get
= ad1983_spdif_route_get
,
3627 .put
= ad1983_spdif_route_put
,
3633 * initialization verbs
3635 static struct hda_verb ad1884a_init_verbs
[] = {
3636 /* DACs; unmute as default */
3637 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3638 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3639 /* Port-A (HP) mixer - route only from analog mixer */
3640 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3641 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3643 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3644 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3645 /* Port-D (Line-out) mixer - route only from analog mixer */
3646 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3647 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3649 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3650 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3651 /* Mono-out mixer - route only from analog mixer */
3652 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3653 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3655 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3656 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3657 /* Port-B (front mic) pin */
3658 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3659 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3660 /* Port-C (rear line-in) pin */
3661 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3662 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3663 /* Port-E (rear mic) pin */
3664 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3665 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3666 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* no boost */
3667 /* Port-F (CD) pin */
3668 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3669 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3670 /* Analog mixer; mute as default */
3671 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3672 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3673 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3674 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3675 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)}, /* aux */
3676 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
3677 /* Analog Mix output amp */
3678 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3679 /* capture sources */
3680 {0x0c, AC_VERB_SET_CONNECT_SEL
, 0x0},
3681 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3682 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
3683 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3684 /* SPDIF output amp */
3685 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
3689 #ifdef CONFIG_SND_HDA_POWER_SAVE
3690 static struct hda_amp_list ad1884a_loopbacks
[] = {
3691 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
3692 { 0x20, HDA_INPUT
, 1 }, /* Mic */
3693 { 0x20, HDA_INPUT
, 2 }, /* CD */
3694 { 0x20, HDA_INPUT
, 4 }, /* Docking */
3702 * Port A: Headphone jack
3704 * Port C: Internal MIC
3705 * Port D: Dock Line Out (if enabled)
3706 * Port E: Dock Line In (if enabled)
3707 * Port F: Internal speakers
3710 static int ad1884a_mobile_master_sw_put(struct snd_kcontrol
*kcontrol
,
3711 struct snd_ctl_elem_value
*ucontrol
)
3713 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
3714 int ret
= snd_hda_mixer_amp_switch_put(kcontrol
, ucontrol
);
3715 int mute
= (!ucontrol
->value
.integer
.value
[0] &&
3716 !ucontrol
->value
.integer
.value
[1]);
3717 /* toggle GPIO1 according to the mute state */
3718 snd_hda_codec_write_cache(codec
, 0x01, 0, AC_VERB_SET_GPIO_DATA
,
3723 static struct snd_kcontrol_new ad1884a_laptop_mixers
[] = {
3724 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3726 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3727 .name
= "Master Playback Switch",
3728 .info
= snd_hda_mixer_amp_switch_info
,
3729 .get
= snd_hda_mixer_amp_switch_get
,
3730 .put
= ad1884a_mobile_master_sw_put
,
3731 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
3733 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
3734 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3735 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3736 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3737 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3738 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
3739 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
3740 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
3741 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
3742 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT
),
3743 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT
),
3744 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT
),
3745 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3746 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3750 static struct snd_kcontrol_new ad1884a_mobile_mixers
[] = {
3751 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3752 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3754 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3755 .name
= "Master Playback Switch",
3756 .info
= snd_hda_mixer_amp_switch_info
,
3757 .get
= snd_hda_mixer_amp_switch_get
,
3758 .put
= ad1884a_mobile_master_sw_put
,
3759 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
3761 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3762 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3763 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT
),
3764 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT
),
3765 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3766 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3770 /* mute internal speaker if HP is plugged */
3771 static void ad1884a_hp_automute(struct hda_codec
*codec
)
3773 unsigned int present
;
3775 present
= snd_hda_codec_read(codec
, 0x11, 0,
3776 AC_VERB_GET_PIN_SENSE
, 0) & 0x80000000;
3777 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
3778 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
3779 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
3780 present
? 0x00 : 0x02);
3783 /* switch to external mic if plugged */
3784 static void ad1884a_hp_automic(struct hda_codec
*codec
)
3786 unsigned int present
;
3788 present
= snd_hda_codec_read(codec
, 0x14, 0,
3789 AC_VERB_GET_PIN_SENSE
, 0) & 0x80000000;
3790 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
,
3794 #define AD1884A_HP_EVENT 0x37
3795 #define AD1884A_MIC_EVENT 0x36
3797 /* unsolicited event for HP jack sensing */
3798 static void ad1884a_hp_unsol_event(struct hda_codec
*codec
, unsigned int res
)
3800 switch (res
>> 26) {
3801 case AD1884A_HP_EVENT
:
3802 ad1884a_hp_automute(codec
);
3804 case AD1884A_MIC_EVENT
:
3805 ad1884a_hp_automic(codec
);
3810 /* initialize jack-sensing, too */
3811 static int ad1884a_hp_init(struct hda_codec
*codec
)
3814 ad1884a_hp_automute(codec
);
3815 ad1884a_hp_automic(codec
);
3819 /* mute internal speaker if HP or docking HP is plugged */
3820 static void ad1884a_laptop_automute(struct hda_codec
*codec
)
3822 unsigned int present
;
3824 present
= snd_hda_codec_read(codec
, 0x11, 0, AC_VERB_GET_PIN_SENSE
, 0);
3825 present
&= AC_PINSENSE_PRESENCE
;
3827 present
= snd_hda_codec_read(codec
, 0x12, 0,
3828 AC_VERB_GET_PIN_SENSE
, 0);
3829 present
&= AC_PINSENSE_PRESENCE
;
3831 snd_hda_codec_amp_stereo(codec
, 0x16, HDA_OUTPUT
, 0,
3832 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
3833 snd_hda_codec_write(codec
, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE
,
3834 present
? 0x00 : 0x02);
3837 /* switch to external mic if plugged */
3838 static void ad1884a_laptop_automic(struct hda_codec
*codec
)
3842 if (snd_hda_codec_read(codec
, 0x14, 0, AC_VERB_GET_PIN_SENSE
, 0) &
3843 AC_PINSENSE_PRESENCE
)
3845 else if (snd_hda_codec_read(codec
, 0x1c, 0, AC_VERB_GET_PIN_SENSE
, 0) &
3846 AC_PINSENSE_PRESENCE
)
3850 snd_hda_codec_write(codec
, 0x0c, 0, AC_VERB_SET_CONNECT_SEL
, idx
);
3853 /* unsolicited event for HP jack sensing */
3854 static void ad1884a_laptop_unsol_event(struct hda_codec
*codec
,
3857 switch (res
>> 26) {
3858 case AD1884A_HP_EVENT
:
3859 ad1884a_laptop_automute(codec
);
3861 case AD1884A_MIC_EVENT
:
3862 ad1884a_laptop_automic(codec
);
3867 /* initialize jack-sensing, too */
3868 static int ad1884a_laptop_init(struct hda_codec
*codec
)
3871 ad1884a_laptop_automute(codec
);
3872 ad1884a_laptop_automic(codec
);
3876 /* additional verbs for laptop model */
3877 static struct hda_verb ad1884a_laptop_verbs
[] = {
3878 /* Port-A (HP) pin - always unmuted */
3879 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3880 /* Port-F (int speaker) mixer - route only from analog mixer */
3881 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3882 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3883 /* Port-F (int speaker) pin */
3884 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3885 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3886 /* required for compaq 6530s/6531s speaker output */
3887 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3888 /* Port-C pin - internal mic-in */
3889 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3890 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
3891 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
3892 /* Port-D (docking line-out) pin - default unmuted */
3893 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3895 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3896 /* unsolicited event for pin-sense */
3897 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
3898 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
3899 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
3900 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
3901 /* allow to touch GPIO1 (for mute control) */
3902 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
3903 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
3904 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
3908 static struct hda_verb ad1884a_mobile_verbs
[] = {
3909 /* DACs; unmute as default */
3910 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3911 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
3912 /* Port-A (HP) mixer - route only from analog mixer */
3913 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3914 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3916 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3917 /* Port-A (HP) pin - always unmuted */
3918 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3919 /* Port-B (mic jack) pin */
3920 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3921 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
3922 /* Port-C (int mic) pin */
3923 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3924 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7002}, /* raise mic as default */
3925 /* Port-F (int speaker) mixer - route only from analog mixer */
3926 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3927 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3929 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3930 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3931 /* Analog mixer; mute as default */
3932 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3933 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3934 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3935 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3936 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3937 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
3938 /* Analog Mix output amp */
3939 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3940 /* capture sources */
3941 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
3942 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3943 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
3944 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3945 /* unsolicited event for pin-sense */
3946 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
3947 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
3948 /* allow to touch GPIO1 (for mute control) */
3949 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
3950 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
3951 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
3960 * 0x17 - built-in mic
3963 static struct hda_verb ad1984a_thinkpad_verbs
[] = {
3965 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3967 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3969 {0x12, AC_VERB_SET_EAPD_BTLENABLE
, 0x02},
3970 /* unsolicited event for pin-sense */
3971 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
3972 /* internal mic - dmic */
3973 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3974 /* set magic COEFs for dmic */
3975 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
3976 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
3980 static struct snd_kcontrol_new ad1984a_thinkpad_mixers
[] = {
3981 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
3982 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT
),
3983 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
3984 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
3985 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
3986 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
3987 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT
),
3988 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT
),
3989 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
3990 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
3992 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3993 .name
= "Capture Source",
3994 .info
= ad198x_mux_enum_info
,
3995 .get
= ad198x_mux_enum_get
,
3996 .put
= ad198x_mux_enum_put
,
4001 static struct hda_input_mux ad1984a_thinkpad_capture_source
= {
4005 { "Internal Mic", 0x5 },
4010 /* mute internal speaker if HP is plugged */
4011 static void ad1984a_thinkpad_automute(struct hda_codec
*codec
)
4013 unsigned int present
;
4015 present
= snd_hda_codec_read(codec
, 0x11, 0, AC_VERB_GET_PIN_SENSE
, 0)
4016 & AC_PINSENSE_PRESENCE
;
4017 snd_hda_codec_amp_stereo(codec
, 0x12, HDA_OUTPUT
, 0,
4018 HDA_AMP_MUTE
, present
? HDA_AMP_MUTE
: 0);
4021 /* unsolicited event for HP jack sensing */
4022 static void ad1984a_thinkpad_unsol_event(struct hda_codec
*codec
,
4025 if ((res
>> 26) != AD1884A_HP_EVENT
)
4027 ad1984a_thinkpad_automute(codec
);
4030 /* initialize jack-sensing, too */
4031 static int ad1984a_thinkpad_init(struct hda_codec
*codec
)
4034 ad1984a_thinkpad_automute(codec
);
4040 * port-A (0x11) - front hp-out
4041 * port-B (0x14) - unused
4042 * port-C (0x15) - unused
4043 * port-D (0x12) - rear line out
4044 * port-E (0x1c) - front mic-in
4045 * port-F (0x16) - Internal speakers
4046 * digital-mic (0x17) - Internal mic
4049 static struct hda_verb ad1984a_touchsmart_verbs
[] = {
4050 /* DACs; unmute as default */
4051 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4052 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x27}, /* 0dB */
4053 /* Port-A (HP) mixer - route only from analog mixer */
4054 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4055 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4057 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4058 /* Port-A (HP) pin - always unmuted */
4059 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4060 /* Port-E (int speaker) mixer - route only from analog mixer */
4061 {0x25, AC_VERB_SET_AMP_GAIN_MUTE
, 0x03},
4063 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4064 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4065 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4066 /* Port-F (int speaker) mixer - route only from analog mixer */
4067 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4068 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4070 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4071 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4072 /* Analog mixer; mute as default */
4073 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4074 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4075 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4076 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4077 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4078 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4079 /* Analog Mix output amp */
4080 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4081 /* capture sources */
4082 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4083 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4084 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0x0},
4085 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4086 /* unsolicited event for pin-sense */
4087 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_HP_EVENT
},
4088 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE
, AC_USRSP_EN
| AD1884A_MIC_EVENT
},
4089 /* allow to touch GPIO1 (for mute control) */
4090 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
4091 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
4092 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02}, /* first muted */
4093 /* internal mic - dmic */
4094 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4095 /* set magic COEFs for dmic */
4096 {0x01, AC_VERB_SET_COEF_INDEX
, 0x13f7},
4097 {0x01, AC_VERB_SET_PROC_COEF
, 0x08},
4101 static struct snd_kcontrol_new ad1984a_touchsmart_mixers
[] = {
4102 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT
),
4103 /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4105 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4106 .name
= "Master Playback Switch",
4107 .info
= snd_hda_mixer_amp_switch_info
,
4108 .get
= snd_hda_mixer_amp_switch_get
,
4109 .put
= ad1884a_mobile_master_sw_put
,
4110 .private_value
= HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT
),
4112 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT
),
4113 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT
),
4114 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4115 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4116 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT
),
4117 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT
),
4121 /* switch to external mic if plugged */
4122 static void ad1984a_touchsmart_automic(struct hda_codec
*codec
)
4124 if (snd_hda_codec_read(codec
, 0x1c, 0,
4125 AC_VERB_GET_PIN_SENSE
, 0) & 0x80000000) {
4126 snd_hda_codec_write(codec
, 0x0c, 0,
4127 AC_VERB_SET_CONNECT_SEL
, 0x4);
4129 snd_hda_codec_write(codec
, 0x0c, 0,
4130 AC_VERB_SET_CONNECT_SEL
, 0x5);
4135 /* unsolicited event for HP jack sensing */
4136 static void ad1984a_touchsmart_unsol_event(struct hda_codec
*codec
,
4139 switch (res
>> 26) {
4140 case AD1884A_HP_EVENT
:
4141 ad1884a_hp_automute(codec
);
4143 case AD1884A_MIC_EVENT
:
4144 ad1984a_touchsmart_automic(codec
);
4149 /* initialize jack-sensing, too */
4150 static int ad1984a_touchsmart_init(struct hda_codec
*codec
)
4153 ad1884a_hp_automute(codec
);
4154 ad1984a_touchsmart_automic(codec
);
4171 static const char *ad1884a_models
[AD1884A_MODELS
] = {
4172 [AD1884A_DESKTOP
] = "desktop",
4173 [AD1884A_LAPTOP
] = "laptop",
4174 [AD1884A_MOBILE
] = "mobile",
4175 [AD1884A_THINKPAD
] = "thinkpad",
4176 [AD1984A_TOUCHSMART
] = "touchsmart",
4179 static struct snd_pci_quirk ad1884a_cfg_tbl
[] = {
4180 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE
),
4181 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP
),
4182 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE
),
4183 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE
),
4184 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP
),
4185 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP
),
4186 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP
),
4187 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE
),
4188 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD
),
4189 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART
),
4193 static int patch_ad1884a(struct hda_codec
*codec
)
4195 struct ad198x_spec
*spec
;
4196 int err
, board_config
;
4198 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4204 err
= snd_hda_attach_beep_device(codec
, 0x10);
4209 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
4211 spec
->multiout
.max_channels
= 2;
4212 spec
->multiout
.num_dacs
= ARRAY_SIZE(ad1884a_dac_nids
);
4213 spec
->multiout
.dac_nids
= ad1884a_dac_nids
;
4214 spec
->multiout
.dig_out_nid
= AD1884A_SPDIF_OUT
;
4215 spec
->num_adc_nids
= ARRAY_SIZE(ad1884a_adc_nids
);
4216 spec
->adc_nids
= ad1884a_adc_nids
;
4217 spec
->capsrc_nids
= ad1884a_capsrc_nids
;
4218 spec
->input_mux
= &ad1884a_capture_source
;
4219 spec
->num_mixers
= 1;
4220 spec
->mixers
[0] = ad1884a_base_mixers
;
4221 spec
->num_init_verbs
= 1;
4222 spec
->init_verbs
[0] = ad1884a_init_verbs
;
4223 spec
->spdif_route
= 0;
4224 #ifdef CONFIG_SND_HDA_POWER_SAVE
4225 spec
->loopback
.amplist
= ad1884a_loopbacks
;
4227 codec
->patch_ops
= ad198x_patch_ops
;
4229 /* override some parameters */
4230 board_config
= snd_hda_check_board_config(codec
, AD1884A_MODELS
,
4233 switch (board_config
) {
4234 case AD1884A_LAPTOP
:
4235 spec
->mixers
[0] = ad1884a_laptop_mixers
;
4236 spec
->init_verbs
[spec
->num_init_verbs
++] = ad1884a_laptop_verbs
;
4237 spec
->multiout
.dig_out_nid
= 0;
4238 codec
->patch_ops
.unsol_event
= ad1884a_laptop_unsol_event
;
4239 codec
->patch_ops
.init
= ad1884a_laptop_init
;
4240 /* set the upper-limit for mixer amp to 0dB for avoiding the
4241 * possible damage by overloading
4243 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4244 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4245 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4246 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4247 (1 << AC_AMPCAP_MUTE_SHIFT
));
4249 case AD1884A_MOBILE
:
4250 spec
->mixers
[0] = ad1884a_mobile_mixers
;
4251 spec
->init_verbs
[0] = ad1884a_mobile_verbs
;
4252 spec
->multiout
.dig_out_nid
= 0;
4253 codec
->patch_ops
.unsol_event
= ad1884a_hp_unsol_event
;
4254 codec
->patch_ops
.init
= ad1884a_hp_init
;
4255 /* set the upper-limit for mixer amp to 0dB for avoiding the
4256 * possible damage by overloading
4258 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4259 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4260 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4261 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4262 (1 << AC_AMPCAP_MUTE_SHIFT
));
4264 case AD1884A_THINKPAD
:
4265 spec
->mixers
[0] = ad1984a_thinkpad_mixers
;
4266 spec
->init_verbs
[spec
->num_init_verbs
++] =
4267 ad1984a_thinkpad_verbs
;
4268 spec
->multiout
.dig_out_nid
= 0;
4269 spec
->input_mux
= &ad1984a_thinkpad_capture_source
;
4270 codec
->patch_ops
.unsol_event
= ad1984a_thinkpad_unsol_event
;
4271 codec
->patch_ops
.init
= ad1984a_thinkpad_init
;
4273 case AD1984A_TOUCHSMART
:
4274 spec
->mixers
[0] = ad1984a_touchsmart_mixers
;
4275 spec
->init_verbs
[0] = ad1984a_touchsmart_verbs
;
4276 spec
->multiout
.dig_out_nid
= 0;
4277 codec
->patch_ops
.unsol_event
= ad1984a_touchsmart_unsol_event
;
4278 codec
->patch_ops
.init
= ad1984a_touchsmart_init
;
4279 /* set the upper-limit for mixer amp to 0dB for avoiding the
4280 * possible damage by overloading
4282 snd_hda_override_amp_caps(codec
, 0x20, HDA_INPUT
,
4283 (0x17 << AC_AMPCAP_OFFSET_SHIFT
) |
4284 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT
) |
4285 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT
) |
4286 (1 << AC_AMPCAP_MUTE_SHIFT
));
4297 * port-A - front hp-out
4298 * port-B - front mic-in
4299 * port-C - rear line-in, shared surr-out (3stack)
4300 * port-D - rear line-out
4301 * port-E - rear mic-in, shared clfe-out (3stack)
4302 * port-F - rear surr-out (6stack)
4303 * port-G - rear clfe-out (6stack)
4306 static hda_nid_t ad1882_dac_nids
[3] = {
4310 static hda_nid_t ad1882_adc_nids
[2] = {
4314 static hda_nid_t ad1882_capsrc_nids
[2] = {
4318 #define AD1882_SPDIF_OUT 0x02
4320 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4321 static struct hda_input_mux ad1882_capture_source
= {
4324 { "Front Mic", 0x1 },
4332 /* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4333 static struct hda_input_mux ad1882a_capture_source
= {
4336 { "Front Mic", 0x1 },
4339 { "Digital Mic", 0x06 },
4344 static struct snd_kcontrol_new ad1882_base_mixers
[] = {
4345 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT
),
4346 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT
),
4347 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT
),
4348 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT
),
4349 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT
),
4350 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT
),
4351 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT
),
4352 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT
),
4354 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT
),
4355 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT
),
4356 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT
),
4357 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT
),
4358 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT
),
4359 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT
),
4360 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT
),
4362 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4363 /* The multiple "Capture Source" controls confuse alsamixer
4364 * So call somewhat different..
4366 /* .name = "Capture Source", */
4367 .name
= "Input Source",
4369 .info
= ad198x_mux_enum_info
,
4370 .get
= ad198x_mux_enum_get
,
4371 .put
= ad198x_mux_enum_put
,
4373 /* SPDIF controls */
4374 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT
),
4376 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4377 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,NONE
) "Source",
4378 /* identical with ad1983 */
4379 .info
= ad1983_spdif_route_info
,
4380 .get
= ad1983_spdif_route_get
,
4381 .put
= ad1983_spdif_route_put
,
4386 static struct snd_kcontrol_new ad1882_loopback_mixers
[] = {
4387 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4388 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4389 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT
),
4390 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT
),
4391 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT
),
4392 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT
),
4393 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4394 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4398 static struct snd_kcontrol_new ad1882a_loopback_mixers
[] = {
4399 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT
),
4400 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT
),
4401 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT
),
4402 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT
),
4403 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT
),
4404 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT
),
4405 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT
),
4406 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT
),
4407 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT
),
4411 static struct snd_kcontrol_new ad1882_3stack_mixers
[] = {
4412 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
4413 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT
),
4414 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT
),
4416 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4417 .name
= "Channel Mode",
4418 .info
= ad198x_ch_mode_info
,
4419 .get
= ad198x_ch_mode_get
,
4420 .put
= ad198x_ch_mode_put
,
4425 static struct snd_kcontrol_new ad1882_6stack_mixers
[] = {
4426 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT
),
4427 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT
),
4428 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT
),
4432 static struct hda_verb ad1882_ch2_init
[] = {
4433 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4434 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4435 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4436 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4437 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4438 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4442 static struct hda_verb ad1882_ch4_init
[] = {
4443 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4444 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4445 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4446 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4447 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4448 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4452 static struct hda_verb ad1882_ch6_init
[] = {
4453 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4454 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4455 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4456 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4457 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4458 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4462 static struct hda_channel_mode ad1882_modes
[3] = {
4463 { 2, ad1882_ch2_init
},
4464 { 4, ad1882_ch4_init
},
4465 { 6, ad1882_ch6_init
},
4469 * initialization verbs
4471 static struct hda_verb ad1882_init_verbs
[] = {
4472 /* DACs; mute as default */
4473 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4474 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4475 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
4476 /* Port-A (HP) mixer */
4477 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4478 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4480 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4481 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4482 /* HP selector - select DAC2 */
4483 {0x37, AC_VERB_SET_CONNECT_SEL
, 0x1},
4484 /* Port-D (Line-out) mixer */
4485 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4486 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4488 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4489 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4490 /* Mono-out mixer */
4491 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4492 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4494 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
4495 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4496 /* Port-B (front mic) pin */
4497 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4498 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4499 {0x39, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4500 /* Port-C (line-in) pin */
4501 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
4502 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4503 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4504 /* Port-C mixer - mute as input */
4505 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4506 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4507 /* Port-E (mic-in) pin */
4508 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
4509 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4510 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
}, /* boost */
4511 /* Port-E mixer - mute as input */
4512 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4513 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4514 /* Port-F (surround) */
4515 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4516 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4518 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
4519 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4520 /* Analog mixer; mute as default */
4521 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4522 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4523 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4524 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
4525 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
4526 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
4527 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)},
4528 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)},
4529 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)},
4530 /* Analog Mix output amp */
4531 {0x21, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x1f}, /* 0dB */
4532 /* SPDIF output selector */
4533 {0x02, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4534 {0x02, AC_VERB_SET_CONNECT_SEL
, 0x0}, /* PCM */
4535 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
| 0x27}, /* 0dB */
4539 #ifdef CONFIG_SND_HDA_POWER_SAVE
4540 static struct hda_amp_list ad1882_loopbacks
[] = {
4541 { 0x20, HDA_INPUT
, 0 }, /* Front Mic */
4542 { 0x20, HDA_INPUT
, 1 }, /* Mic */
4543 { 0x20, HDA_INPUT
, 4 }, /* Line */
4544 { 0x20, HDA_INPUT
, 6 }, /* CD */
4556 static const char *ad1882_models
[AD1986A_MODELS
] = {
4557 [AD1882_3STACK
] = "3stack",
4558 [AD1882_6STACK
] = "6stack",
4562 static int patch_ad1882(struct hda_codec
*codec
)
4564 struct ad198x_spec
*spec
;
4565 int err
, board_config
;
4567 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
4573 err
= snd_hda_attach_beep_device(codec
, 0x10);
4578 set_beep_amp(spec
, 0x10, 0, HDA_OUTPUT
);
4580 spec
->multiout
.max_channels
= 6;
4581 spec
->multiout
.num_dacs
= 3;
4582 spec
->multiout
.dac_nids
= ad1882_dac_nids
;
4583 spec
->multiout
.dig_out_nid
= AD1882_SPDIF_OUT
;
4584 spec
->num_adc_nids
= ARRAY_SIZE(ad1882_adc_nids
);
4585 spec
->adc_nids
= ad1882_adc_nids
;
4586 spec
->capsrc_nids
= ad1882_capsrc_nids
;
4587 if (codec
->vendor_id
== 0x11d41882)
4588 spec
->input_mux
= &ad1882_capture_source
;
4590 spec
->input_mux
= &ad1882a_capture_source
;
4591 spec
->num_mixers
= 2;
4592 spec
->mixers
[0] = ad1882_base_mixers
;
4593 if (codec
->vendor_id
== 0x11d41882)
4594 spec
->mixers
[1] = ad1882_loopback_mixers
;
4596 spec
->mixers
[1] = ad1882a_loopback_mixers
;
4597 spec
->num_init_verbs
= 1;
4598 spec
->init_verbs
[0] = ad1882_init_verbs
;
4599 spec
->spdif_route
= 0;
4600 #ifdef CONFIG_SND_HDA_POWER_SAVE
4601 spec
->loopback
.amplist
= ad1882_loopbacks
;
4603 spec
->vmaster_nid
= 0x04;
4605 codec
->patch_ops
= ad198x_patch_ops
;
4607 /* override some parameters */
4608 board_config
= snd_hda_check_board_config(codec
, AD1882_MODELS
,
4609 ad1882_models
, NULL
);
4610 switch (board_config
) {
4613 spec
->num_mixers
= 3;
4614 spec
->mixers
[2] = ad1882_3stack_mixers
;
4615 spec
->channel_mode
= ad1882_modes
;
4616 spec
->num_channel_mode
= ARRAY_SIZE(ad1882_modes
);
4617 spec
->need_dac_fix
= 1;
4618 spec
->multiout
.max_channels
= 2;
4619 spec
->multiout
.num_dacs
= 1;
4622 spec
->num_mixers
= 3;
4623 spec
->mixers
[2] = ad1882_6stack_mixers
;
4633 static struct hda_codec_preset snd_hda_preset_analog
[] = {
4634 { .id
= 0x11d4184a, .name
= "AD1884A", .patch
= patch_ad1884a
},
4635 { .id
= 0x11d41882, .name
= "AD1882", .patch
= patch_ad1882
},
4636 { .id
= 0x11d41883, .name
= "AD1883", .patch
= patch_ad1884a
},
4637 { .id
= 0x11d41884, .name
= "AD1884", .patch
= patch_ad1884
},
4638 { .id
= 0x11d4194a, .name
= "AD1984A", .patch
= patch_ad1884a
},
4639 { .id
= 0x11d4194b, .name
= "AD1984B", .patch
= patch_ad1884a
},
4640 { .id
= 0x11d41981, .name
= "AD1981", .patch
= patch_ad1981
},
4641 { .id
= 0x11d41983, .name
= "AD1983", .patch
= patch_ad1983
},
4642 { .id
= 0x11d41984, .name
= "AD1984", .patch
= patch_ad1984
},
4643 { .id
= 0x11d41986, .name
= "AD1986A", .patch
= patch_ad1986a
},
4644 { .id
= 0x11d41988, .name
= "AD1988", .patch
= patch_ad1988
},
4645 { .id
= 0x11d4198b, .name
= "AD1988B", .patch
= patch_ad1988
},
4646 { .id
= 0x11d4882a, .name
= "AD1882A", .patch
= patch_ad1882
},
4647 { .id
= 0x11d4989a, .name
= "AD1989A", .patch
= patch_ad1988
},
4648 { .id
= 0x11d4989b, .name
= "AD1989B", .patch
= patch_ad1988
},
4652 MODULE_ALIAS("snd-hda-codec-id:11d4*");
4654 MODULE_LICENSE("GPL");
4655 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4657 static struct hda_codec_preset_list analog_list
= {
4658 .preset
= snd_hda_preset_analog
,
4659 .owner
= THIS_MODULE
,
4662 static int __init
patch_analog_init(void)
4664 return snd_hda_add_codec_preset(&analog_list
);
4667 static void __exit
patch_analog_exit(void)
4669 snd_hda_delete_codec_preset(&analog_list
);
4672 module_init(patch_analog_init
)
4673 module_exit(patch_analog_exit
)