2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for ALC 260/880/882 codecs
6 * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
7 * Takashi Iwai <tiwai@suse.de>
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sound/driver.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/pci.h>
29 #include <sound/core.h>
30 #include "hda_codec.h"
31 #include "hda_local.h"
34 /* ALC880 board config type */
49 ALC880_MODEL_LAST
/* last tag */
56 ALC260_MODEL_LAST
/* last tag */
60 /* codec parameterization */
61 unsigned int front_panel
: 1; /* indicates the board has a front panel;
62 * not referred currently for any purpose,
66 snd_kcontrol_new_t
*mixers
[2]; /* mixer arrays */
67 unsigned int num_mixers
;
69 struct hda_verb
*init_verbs
; /* initialization verbs
70 * don't forget NULL termination!
73 char *stream_name_analog
; /* analog PCM stream */
74 struct hda_pcm_stream
*stream_analog_playback
;
75 struct hda_pcm_stream
*stream_analog_capture
;
77 char *stream_name_digital
; /* digital PCM stream */
78 struct hda_pcm_stream
*stream_digital_playback
;
79 struct hda_pcm_stream
*stream_digital_capture
;
82 struct hda_multi_out multiout
; /* playback set-up
83 * max_channels, dacs must be set
84 * dig_out_nid and hp_nid are optional
88 unsigned int num_adc_nids
;
90 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
93 const struct hda_input_mux
*input_mux
;
94 unsigned int cur_mux
[3];
97 const struct alc_channel_mode
*channel_mode
;
100 /* PCM information */
101 struct hda_pcm pcm_rec
[2]; /* used in alc_build_pcms() */
103 struct semaphore bind_mutex
; /* for bound controls */
106 /* DAC/ADC assignment */
108 static hda_nid_t alc880_dac_nids
[4] = {
109 /* front, rear, clfe, rear_surr */
110 0x02, 0x05, 0x04, 0x03
113 static hda_nid_t alc880_6st_dac_nids
[4] = {
114 /* front, rear, clfe, rear_surr */
115 0x02, 0x03, 0x04, 0x05
118 static hda_nid_t alc880_w810_dac_nids
[3] = {
119 /* front, rear/surround, clfe */
123 static hda_nid_t alc880_z71v_dac_nids
[1] = {
129 /* The datasheet says the node 0x07 is connected from inputs,
130 * but it shows zero connection in the real implementation on some devices.
132 static hda_nid_t alc880_adc_nids
[3] = {
137 static hda_nid_t alc880_adc_nids
[2] = {
143 #define ALC880_DIGOUT_NID 0x06
144 #define ALC880_DIGIN_NID 0x0a
146 static hda_nid_t alc260_dac_nids
[1] = {
151 static hda_nid_t alc260_adc_nids
[1] = {
156 static hda_nid_t alc260_hp_adc_nids
[1] = {
161 #define ALC260_DIGOUT_NID 0x03
162 #define ALC260_DIGIN_NID 0x06
164 static struct hda_input_mux alc880_capture_source
= {
168 { "Front Mic", 0x3 },
175 static struct hda_input_mux alc880_6stack_capture_source
= {
179 { "Front Mic", 0x1 },
185 static struct hda_input_mux alc260_capture_source
= {
189 { "Front Mic", 0x1 },
198 static int alc_mux_enum_info(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_info_t
*uinfo
)
200 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
201 struct alc_spec
*spec
= codec
->spec
;
202 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
205 static int alc_mux_enum_get(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
207 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
208 struct alc_spec
*spec
= codec
->spec
;
209 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
211 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
215 static int alc_mux_enum_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
217 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
218 struct alc_spec
*spec
= codec
->spec
;
219 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
220 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
221 spec
->adc_nids
[adc_idx
], &spec
->cur_mux
[adc_idx
]);
225 * channel mode setting
227 struct alc_channel_mode
{
229 const struct hda_verb
*sequence
;
234 * channel source setting (2/6 channel selection for 3-stack)
238 * set the path ways for 2 channel output
239 * need to set the codec line out and mic 1 pin widgets to inputs
241 static struct hda_verb alc880_threestack_ch2_init
[] = {
242 /* set pin widget 1Ah (line in) for input */
243 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
244 /* set pin widget 18h (mic1) for input, for mic also enable the vref */
245 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
246 /* mute the output for Line In PW */
247 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
248 /* mute for Mic1 PW */
249 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
255 * need to set the codec line out and mic 1 pin widgets to outputs
257 static struct hda_verb alc880_threestack_ch6_init
[] = {
258 /* set pin widget 1Ah (line in) for output */
259 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
260 /* set pin widget 18h (mic1) for output */
261 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
262 /* unmute the output for Line In PW */
263 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000 },
264 /* unmute for Mic1 PW */
265 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000 },
266 /* for rear channel output using Line In 1
267 * set select widget connection (nid = 0x12) - to summer node
268 * for rear NID = 0x0f...offset 3 in connection list
270 { 0x12, AC_VERB_SET_CONNECT_SEL
, 0x3 },
271 /* for Mic1 - retask for center/lfe */
272 /* set select widget connection (nid = 0x10) - to summer node for
273 * front CLFE NID = 0x0e...offset 2 in connection list
275 { 0x10, AC_VERB_SET_CONNECT_SEL
, 0x2 },
279 static struct alc_channel_mode alc880_threestack_modes
[2] = {
280 { 2, alc880_threestack_ch2_init
},
281 { 6, alc880_threestack_ch6_init
},
286 * channel source setting (6/8 channel selection for 5-stack)
289 /* set the path ways for 6 channel output
290 * need to set the codec line out and mic 1 pin widgets to inputs
292 static struct hda_verb alc880_fivestack_ch6_init
[] = {
293 /* set pin widget 1Ah (line in) for input */
294 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
295 /* mute the output for Line In PW */
296 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
300 /* need to set the codec line out and mic 1 pin widgets to outputs */
301 static struct hda_verb alc880_fivestack_ch8_init
[] = {
302 /* set pin widget 1Ah (line in) for output */
303 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
304 /* unmute the output for Line In PW */
305 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000 },
306 /* output for surround channel output using Line In 1 */
307 /* set select widget connection (nid = 0x12) - to summer node
308 * for surr_rear NID = 0x0d...offset 1 in connection list
310 { 0x12, AC_VERB_SET_CONNECT_SEL
, 0x1 },
314 static struct alc_channel_mode alc880_fivestack_modes
[2] = {
315 { 6, alc880_fivestack_ch6_init
},
316 { 8, alc880_fivestack_ch8_init
},
320 * channel source setting for W810 system
322 * W810 has rear IO for:
325 * Center/LFE (DAC 04)
328 * The system also has a pair of internal speakers, and a headphone jack.
329 * These are both connected to Line2 on the codec, hence to DAC 02.
331 * There is a variable resistor to control the speaker or headphone
332 * volume. This is a hardware-only device without a software API.
334 * Plugging headphones in will disable the internal speakers. This is
335 * implemented in hardware, not via the driver using jack sense. In
336 * a similar fashion, plugging into the rear socket marked "front" will
337 * disable both the speakers and headphones.
339 * For input, there's a microphone jack, and an "audio in" jack.
340 * These may not do anything useful with this driver yet, because I
341 * haven't setup any initialization verbs for these yet...
344 static struct alc_channel_mode alc880_w810_modes
[1] = {
348 static struct alc_channel_mode alc880_z71v_modes
[1] = {
353 static struct alc_channel_mode alc880_sixstack_modes
[1] = {
359 static int alc880_ch_mode_info(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_info_t
*uinfo
)
361 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
362 struct alc_spec
*spec
= codec
->spec
;
363 int items
= kcontrol
->private_value
? (int)kcontrol
->private_value
: 2;
365 snd_assert(spec
->channel_mode
, return -ENXIO
);
366 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
368 uinfo
->value
.enumerated
.items
= items
;
369 if (uinfo
->value
.enumerated
.item
>= items
)
370 uinfo
->value
.enumerated
.item
= items
- 1;
371 sprintf(uinfo
->value
.enumerated
.name
, "%dch",
372 spec
->channel_mode
[uinfo
->value
.enumerated
.item
].channels
);
376 static int alc880_ch_mode_get(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
378 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
379 struct alc_spec
*spec
= codec
->spec
;
380 int items
= kcontrol
->private_value
? (int)kcontrol
->private_value
: 2;
383 snd_assert(spec
->channel_mode
, return -ENXIO
);
384 for (i
= 0; i
< items
; i
++) {
385 if (spec
->multiout
.max_channels
== spec
->channel_mode
[i
].channels
) {
386 ucontrol
->value
.enumerated
.item
[0] = i
;
393 static int alc880_ch_mode_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
395 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
396 struct alc_spec
*spec
= codec
->spec
;
399 snd_assert(spec
->channel_mode
, return -ENXIO
);
400 mode
= ucontrol
->value
.enumerated
.item
[0] ? 1 : 0;
401 if (spec
->multiout
.max_channels
== spec
->channel_mode
[mode
].channels
&&
405 /* change the current channel setting */
406 spec
->multiout
.max_channels
= spec
->channel_mode
[mode
].channels
;
407 if (spec
->channel_mode
[mode
].sequence
)
408 snd_hda_sequence_write(codec
, spec
->channel_mode
[mode
].sequence
);
415 * bound volume controls
417 * bind multiple volumes (# indices, from 0)
420 #define AMP_VAL_IDX_SHIFT 19
421 #define AMP_VAL_IDX_MASK (0x0f<<19)
423 static int alc_bind_switch_info(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_info_t
*uinfo
)
425 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
426 struct alc_spec
*spec
= codec
->spec
;
429 down(&spec
->bind_mutex
);
430 pval
= kcontrol
->private_value
;
431 kcontrol
->private_value
= pval
& ~AMP_VAL_IDX_MASK
; /* index 0 */
432 snd_hda_mixer_amp_switch_info(kcontrol
, uinfo
);
433 kcontrol
->private_value
= pval
;
434 up(&spec
->bind_mutex
);
438 static int alc_bind_switch_get(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
440 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
441 struct alc_spec
*spec
= codec
->spec
;
444 down(&spec
->bind_mutex
);
445 pval
= kcontrol
->private_value
;
446 kcontrol
->private_value
= pval
& ~AMP_VAL_IDX_MASK
; /* index 0 */
447 snd_hda_mixer_amp_switch_get(kcontrol
, ucontrol
);
448 kcontrol
->private_value
= pval
;
449 up(&spec
->bind_mutex
);
453 static int alc_bind_switch_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
455 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
456 struct alc_spec
*spec
= codec
->spec
;
458 int i
, indices
, change
= 0;
460 down(&spec
->bind_mutex
);
461 pval
= kcontrol
->private_value
;
462 indices
= (pval
& AMP_VAL_IDX_MASK
) >> AMP_VAL_IDX_SHIFT
;
463 for (i
= 0; i
< indices
; i
++) {
464 kcontrol
->private_value
= (pval
& ~AMP_VAL_IDX_MASK
) | (i
<< AMP_VAL_IDX_SHIFT
);
465 change
|= snd_hda_mixer_amp_switch_put(kcontrol
, ucontrol
);
467 kcontrol
->private_value
= pval
;
468 up(&spec
->bind_mutex
);
472 #define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
473 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
474 .info = alc_bind_switch_info, \
475 .get = alc_bind_switch_get, \
476 .put = alc_bind_switch_put, \
477 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
479 #define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
485 * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
488 static snd_kcontrol_new_t alc880_base_mixer
[] = {
489 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
490 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
491 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
492 ALC_BIND_MUTE("Surround Playback Switch", 0x1a, 2, HDA_INPUT
),
493 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
494 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
495 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
496 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
497 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
498 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
499 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
500 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
501 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
502 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
503 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT
),
504 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT
),
505 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
506 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
507 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
508 ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT
),
509 /* We don't use NID 0x07 - see above */
510 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
511 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
512 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
513 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
515 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
516 /* The multiple "Capture Source" controls confuse alsamixer
517 * So call somewhat different..
518 * FIXME: the controls appear in the "playback" view!
520 /* .name = "Capture Source", */
521 .name
= "Input Source",
523 .info
= alc_mux_enum_info
,
524 .get
= alc_mux_enum_get
,
525 .put
= alc_mux_enum_put
,
528 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
529 .name
= "Channel Mode",
530 .info
= alc880_ch_mode_info
,
531 .get
= alc880_ch_mode_get
,
532 .put
= alc880_ch_mode_put
,
538 * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
539 * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
541 static snd_kcontrol_new_t alc880_five_stack_mixer
[] = {
542 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
543 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
544 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
545 ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT
),
546 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
547 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
548 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
549 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
550 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
551 ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT
),
552 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
553 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
554 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
555 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
556 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
557 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
558 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT
),
559 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT
),
560 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
561 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
562 /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), */
563 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT
),
564 /* We don't use NID 0x07 - see above */
565 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
566 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
567 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
568 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
570 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
571 /* The multiple "Capture Source" controls confuse alsamixer
572 * So call somewhat different..
573 * FIXME: the controls appear in the "playback" view!
575 /* .name = "Capture Source", */
576 .name
= "Input Source",
578 .info
= alc_mux_enum_info
,
579 .get
= alc_mux_enum_get
,
580 .put
= alc_mux_enum_put
,
583 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
584 .name
= "Channel Mode",
585 .info
= alc880_ch_mode_info
,
586 .get
= alc880_ch_mode_get
,
587 .put
= alc880_ch_mode_put
,
592 static snd_kcontrol_new_t alc880_w810_base_mixer
[] = {
593 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
594 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT
),
595 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
596 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
597 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
598 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
599 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT
),
600 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT
),
601 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
602 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
603 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
604 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
605 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
606 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
607 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
609 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
610 /* The multiple "Capture Source" controls confuse alsamixer
611 * So call somewhat different..
612 * FIXME: the controls appear in the "playback" view!
614 /* .name = "Capture Source", */
615 .name
= "Input Source",
617 .info
= alc_mux_enum_info
,
618 .get
= alc_mux_enum_get
,
619 .put
= alc_mux_enum_put
,
624 static snd_kcontrol_new_t alc880_z71v_mixer
[] = {
625 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
626 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
627 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
628 ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT
),
629 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
630 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
631 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
632 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
633 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
634 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
635 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
636 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
637 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
638 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
640 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
641 /* The multiple "Capture Source" controls confuse alsamixer
642 * So call somewhat different..
643 * FIXME: the controls appear in the "playback" view!
645 /* .name = "Capture Source", */
646 .name
= "Input Source",
648 .info
= alc_mux_enum_info
,
649 .get
= alc_mux_enum_get
,
650 .put
= alc_mux_enum_put
,
656 static snd_kcontrol_new_t alc880_six_stack_mixer
[] = {
657 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
658 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
659 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
660 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
661 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
662 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
663 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
664 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
665 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
666 ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
667 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
668 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
669 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
670 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
671 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
672 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
673 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
674 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
675 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
676 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
677 /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), */
678 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
679 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
680 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
681 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
682 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
684 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
685 /* The multiple "Capture Source" controls confuse alsamixer
686 * So call somewhat different..
687 * FIXME: the controls appear in the "playback" view!
689 /* .name = "Capture Source", */
690 .name
= "Input Source",
692 .info
= alc_mux_enum_info
,
693 .get
= alc_mux_enum_get
,
694 .put
= alc_mux_enum_put
,
697 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
698 .name
= "Channel Mode",
699 .info
= alc880_ch_mode_info
,
700 .get
= alc880_ch_mode_get
,
701 .put
= alc880_ch_mode_put
,
707 static snd_kcontrol_new_t alc880_2_jack_mixer
[] = {
708 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
709 ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT
),
710 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
711 ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT
),
712 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
713 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
714 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
715 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
716 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
717 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
719 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
720 /* The multiple "Capture Source" controls confuse alsamixer
721 * So call somewhat different..
722 * FIXME: the controls appear in the "playback" view!
724 /* .name = "Capture Source", */
725 .name
= "Input Source",
727 .info
= alc_mux_enum_info
,
728 .get
= alc_mux_enum_get
,
729 .put
= alc_mux_enum_put
,
735 static snd_kcontrol_new_t alc880_asus_mixer
[] = {
736 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
737 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
738 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
739 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
740 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
741 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
742 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
743 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
744 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
745 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
746 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
747 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
748 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
749 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
750 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
751 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
752 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
753 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
755 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
756 /* The multiple "Capture Source" controls confuse alsamixer
757 * So call somewhat different..
758 * FIXME: the controls appear in the "playback" view!
760 /* .name = "Capture Source", */
761 .name
= "Input Source",
763 .info
= alc_mux_enum_info
,
764 .get
= alc_mux_enum_get
,
765 .put
= alc_mux_enum_put
,
768 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
769 .name
= "Channel Mode",
770 .info
= alc880_ch_mode_info
,
771 .get
= alc880_ch_mode_get
,
772 .put
= alc880_ch_mode_put
,
778 static snd_kcontrol_new_t alc880_asus_w1v_mixer
[] = {
779 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
780 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
781 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
782 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
783 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
784 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
785 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
786 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
787 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
788 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
789 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
790 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
791 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT
),
792 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT
),
793 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
794 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
795 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
796 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
797 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
798 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
800 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
801 /* The multiple "Capture Source" controls confuse alsamixer
802 * So call somewhat different..
803 * FIXME: the controls appear in the "playback" view!
805 /* .name = "Capture Source", */
806 .name
= "Input Source",
808 .info
= alc_mux_enum_info
,
809 .get
= alc_mux_enum_get
,
810 .put
= alc_mux_enum_put
,
813 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
814 .name
= "Channel Mode",
815 .info
= alc880_ch_mode_info
,
816 .get
= alc880_ch_mode_get
,
817 .put
= alc880_ch_mode_put
,
823 static int alc_build_controls(struct hda_codec
*codec
)
825 struct alc_spec
*spec
= codec
->spec
;
829 for (i
= 0; i
< spec
->num_mixers
; i
++) {
830 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
835 if (spec
->multiout
.dig_out_nid
) {
836 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
840 if (spec
->dig_in_nid
) {
841 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
849 * initialize the codec volumes, etc
852 #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
853 #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
854 #define AMP_OUT_MUTE 0xb080
855 #define AMP_OUT_UNMUTE 0xb000
856 #define AMP_OUT_ZERO 0xb000
858 #define PIN_VREF80 0x24
859 #define PIN_VREF50 0x21
863 static struct hda_verb alc880_init_verbs_three_stack
[] = {
864 /* Set pin widgets for output */
865 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
866 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
867 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
868 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
869 /* Line In pin widget for input */
870 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
871 /* CD pin widget for input */
872 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
873 /* Mic1 (rear panel) pin widget for input and vref at 80% */
874 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
875 /* Mic2 (front panel) pin widget for input and vref at 80% */
876 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
877 /* unmute capture amp left and right */
878 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
879 /* set connection select to mic in */
880 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
881 /* unmute capture1 amp left and right */
882 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
883 /* set connection select to mic in */
884 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
885 /* unmute capture2 amp left and right */
886 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
887 /* set connection select to mic in */
888 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
889 /* set vol=0 front mixer amp */
890 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
891 /* unmute front-out pin widget amp (no gain on this amp) */
892 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
893 /* set vol=0 rear mixer amp */
894 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
895 /* mute line-in pin widget amp left and right (no gain on this amp) */
896 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
897 /* set vol=0 clfe mixer amp */
898 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
899 /* mute mic pin widget amp left and right (no gain on this amp) */
900 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
902 /* using rear surround as the path for headphone output */
903 /* set vol=0 rear surround mixer amp */
904 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
905 /* PASD 3 stack boards use the Mic 2 as the headphone output */
906 /* need to program the selector associated with the Mic 2 pin widget to
907 * surround path (index 0x01) for headphone output */
908 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x01},
909 /* unmute pin widget amp left and right (no gain on this amp) */
910 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
911 /* need to retask the Mic 2 pin widget to output */
912 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
914 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
915 * to support the input path of analog loopback
916 * Note: PASD motherboards uses the Line In 2 as the input for front panel
919 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
921 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
923 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
925 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
926 /* mute Line In 2 (for PASD boards Mic 2) */
927 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
929 /* Unmute input amps for the line out paths to support the output path of
931 * the mixers on the output path has 2 inputs, one from the DAC and one
934 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
935 /* Unmute Front out path */
936 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
937 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
938 /* Unmute Surround (used as HP) out path */
939 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
940 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
941 /* Unmute C/LFE out path */
942 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
943 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
944 /* Unmute rear Surround out path */
945 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
946 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
951 static struct hda_verb alc880_init_verbs_five_stack
[] = {
952 /* Set pin widgets for output */
953 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
954 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
955 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
956 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
957 /* Line In pin widget for input */
958 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
959 /* CD pin widget for input */
960 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
961 /* Mic1 (rear panel) pin widget for input and vref at 80% */
962 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
963 /* Mic2 (front panel) pin widget for input and vref at 80% */
964 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
965 /* mute capture amp left and right */
966 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
967 /* set connection select to mic in */
968 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
969 /* mute amp1 left and right */
970 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
971 /* set connection select to mic in */
972 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
973 /* mute amp left and right */
974 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
975 /* set connection select to mic in */
976 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
977 /* set vol=0 front mixer amp */
978 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
979 /* unmute front-out pin widget amp (no gain on this amp) */
980 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
981 /* set vol=0 rear mixer amp */
982 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
983 /* unmute rear-out pin widget (no gain on this amp) */
984 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
985 /* set vol=0 clfe mixer amp */
986 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
987 /* unmute clfe-pin widget amp (no gain on this amp) */
988 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
990 /* using rear surround as the path for headphone output */
991 /* set vol=0 rear surround mixer amp */
992 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
993 /* PASD 3 stack boards use the Mic 2 as the headphone output */
994 /* need to program the selector associated with the Mic 2 pin widget to
995 * surround path (index 0x01) for headphone output
997 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x01},
998 /* mute pin widget amp left and right (no gain on this amp) */
999 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1000 /* need to retask the Mic 2 pin widget to output */
1001 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1003 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
1004 * widget(nid=0x0B) to support the input path of analog loopback
1006 /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
1007 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
1009 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1010 /* unmute Line In */
1011 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1013 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1014 /* unmute Line In 2 (for PASD boards Mic 2) */
1015 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1017 /* Unmute input amps for the line out paths to support the output path of
1019 * the mixers on the output path has 2 inputs, one from the DAC and
1020 * one from the mixer
1022 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
1023 /* Unmute Front out path */
1024 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1025 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1026 /* Unmute Surround (used as HP) out path */
1027 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1028 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1029 /* Unmute C/LFE out path */
1030 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1031 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1032 /* Unmute rear Surround out path */
1033 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1034 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1039 static struct hda_verb alc880_w810_init_verbs
[] = {
1040 /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
1041 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1043 /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
1044 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1046 /* front channel selector/amp: output 0: unmuted, max volume */
1047 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1049 /* front out pin: muted, (no volume selection) */
1050 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1052 /* front out pin: NOT headphone enable, out enable, vref disabled */
1053 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1056 /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
1057 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1059 /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
1060 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1062 /* surround channel selector/amp: output 0: unmuted, max volume */
1063 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1065 /* surround out pin: muted, (no volume selection) */
1066 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1068 /* surround out pin: NOT headphone enable, out enable, vref disabled */
1069 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1072 /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
1073 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1075 /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
1076 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1078 /* c/lfe channel selector/amp: output 0: unmuted, max volume */
1079 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1081 /* c/lfe out pin: muted, (no volume selection) */
1082 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1084 /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
1085 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1088 /* hphone/speaker input selector: front DAC */
1089 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x0},
1091 /* hphone/speaker out pin: muted, (no volume selection) */
1092 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1094 /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
1095 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1101 static struct hda_verb alc880_z71v_init_verbs
[] = {
1102 /* front channel selector/amp: muted, DAC and mix (no vol) */
1103 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1104 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1105 /* front channel selector/amp: output 0: vol=0 */
1106 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1107 /* front out pin: unmuted, (no volume selection) */
1108 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1109 /* front out pin: NOT headphone enable, out enable, vref disabled */
1110 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1111 /* headphone channel selector/amp: muted, DAC and mix (no vol) */
1112 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1113 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1114 /* headphone channel selector/amp: output 0: vol=0 */
1115 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1116 /* headphone out pin: muted, (no volume selection) */
1117 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1118 /* headpohne out pin: headphone enable, out enable, vref disabled */
1119 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1121 /* Line In pin widget for input */
1122 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1123 /* CD pin widget for input */
1124 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1125 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1126 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1127 /* Mic2 (front panel) pin widget for input and vref at 80% */
1128 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1129 /* unmute amp left and right */
1130 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1131 /* set connection select to mic in */
1132 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
1133 /* unmute amp left and right */
1134 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1135 /* set connection select to mic in */
1136 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
1137 /* unmute amp left and right */
1138 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1139 /* set connection select to mic in */
1140 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
1141 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
1142 * widget(nid=0x0B) to support the input path of analog loopback
1144 /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
1145 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
1147 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1148 /* unmute Line In */
1149 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1151 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1152 /* unmute Line In 2 (for PASD boards Mic 2) */
1153 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1159 static struct hda_verb alc880_six_stack_init_verbs
[] = {
1160 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1161 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1162 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1163 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1164 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1165 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1166 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1167 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1168 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1170 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1171 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1172 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1173 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1175 /* unmute amp left and right */
1176 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1177 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x02},
1178 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1179 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1180 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1181 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1182 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1183 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1184 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1185 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1186 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1188 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
1189 * widget(nid=0x0B) to support the input path of analog loopback
1191 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1192 /* unmute Line In */
1193 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1195 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1197 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1199 /* Unmute Front out path */
1200 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1201 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1202 /* Unmute Surround (used as HP) out path */
1203 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1204 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1205 /* Unmute C/LFE out path */
1206 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1207 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)}, /* mute */
1208 /* Unmute rear Surround out path */
1209 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1210 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1215 static struct hda_verb alc880_2_jack_init_verbs
[] = {
1216 /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
1217 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1218 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1219 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1220 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1221 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1222 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1223 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1224 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1225 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1226 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1227 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1228 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1229 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x02},
1230 {0x0C, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1231 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1232 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1233 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1234 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1235 {0x1B, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1236 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1237 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1238 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1239 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1240 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1241 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1242 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1247 static struct hda_verb alc880_asus_init_verbs
[] = {
1248 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1249 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1250 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1251 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1253 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1254 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1255 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1256 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1257 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF50
},
1258 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF50
},
1259 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF50
},
1260 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1261 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1263 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
1265 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1266 /* unmute Line In */
1267 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1269 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1270 /* unmute Line In 2 (for PASD boards Mic 2) */
1271 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1273 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
1274 /* Unmute Front out path */
1275 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1276 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1277 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1278 /* Unmute Surround (used as HP) out path */
1279 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1280 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1281 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1282 /* Unmute C/LFE out path */
1283 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1284 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1285 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1291 static int alc_init(struct hda_codec
*codec
)
1293 struct alc_spec
*spec
= codec
->spec
;
1294 snd_hda_sequence_write(codec
, spec
->init_verbs
);
1302 static int alc_resume(struct hda_codec
*codec
)
1304 struct alc_spec
*spec
= codec
->spec
;
1308 for (i
= 0; i
< spec
->num_mixers
; i
++) {
1309 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
1311 if (spec
->multiout
.dig_out_nid
)
1312 snd_hda_resume_spdif_out(codec
);
1313 if (spec
->dig_in_nid
)
1314 snd_hda_resume_spdif_in(codec
);
1321 * Analog playback callbacks
1323 static int alc880_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1324 struct hda_codec
*codec
,
1325 snd_pcm_substream_t
*substream
)
1327 struct alc_spec
*spec
= codec
->spec
;
1328 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
1331 static int alc880_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1332 struct hda_codec
*codec
,
1333 unsigned int stream_tag
,
1334 unsigned int format
,
1335 snd_pcm_substream_t
*substream
)
1337 struct alc_spec
*spec
= codec
->spec
;
1338 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
1342 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1343 struct hda_codec
*codec
,
1344 snd_pcm_substream_t
*substream
)
1346 struct alc_spec
*spec
= codec
->spec
;
1347 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
1353 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1354 struct hda_codec
*codec
,
1355 snd_pcm_substream_t
*substream
)
1357 struct alc_spec
*spec
= codec
->spec
;
1358 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
1361 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
1362 struct hda_codec
*codec
,
1363 snd_pcm_substream_t
*substream
)
1365 struct alc_spec
*spec
= codec
->spec
;
1366 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
1372 static int alc880_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1373 struct hda_codec
*codec
,
1374 unsigned int stream_tag
,
1375 unsigned int format
,
1376 snd_pcm_substream_t
*substream
)
1378 struct alc_spec
*spec
= codec
->spec
;
1380 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
1381 stream_tag
, 0, format
);
1385 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1386 struct hda_codec
*codec
,
1387 snd_pcm_substream_t
*substream
)
1389 struct alc_spec
*spec
= codec
->spec
;
1391 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
], 0, 0, 0);
1398 static struct hda_pcm_stream alc880_pcm_analog_playback
= {
1402 .nid
= 0x02, /* NID to query formats and rates */
1404 .open
= alc880_playback_pcm_open
,
1405 .prepare
= alc880_playback_pcm_prepare
,
1406 .cleanup
= alc880_playback_pcm_cleanup
1410 static struct hda_pcm_stream alc880_pcm_analog_capture
= {
1414 .nid
= 0x08, /* NID to query formats and rates
1415 * (0x07 might be broken on some devices)
1418 .prepare
= alc880_capture_pcm_prepare
,
1419 .cleanup
= alc880_capture_pcm_cleanup
1423 static struct hda_pcm_stream alc880_pcm_digital_playback
= {
1427 /* NID is set in alc_build_pcms */
1429 .open
= alc880_dig_playback_pcm_open
,
1430 .close
= alc880_dig_playback_pcm_close
1434 static struct hda_pcm_stream alc880_pcm_digital_capture
= {
1438 /* NID is set in alc_build_pcms */
1441 static int alc_build_pcms(struct hda_codec
*codec
)
1443 struct alc_spec
*spec
= codec
->spec
;
1444 struct hda_pcm
*info
= spec
->pcm_rec
;
1447 codec
->num_pcms
= 1;
1448 codec
->pcm_info
= info
;
1450 info
->name
= spec
->stream_name_analog
;
1451 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
1452 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
1454 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= 0;
1455 for (i
= 0; i
< spec
->num_channel_mode
; i
++) {
1456 if (spec
->channel_mode
[i
].channels
> info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
) {
1457 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->channel_mode
[i
].channels
;
1461 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
1464 info
->name
= spec
->stream_name_digital
;
1465 if (spec
->multiout
.dig_out_nid
) {
1466 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_digital_playback
);
1467 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
1469 if (spec
->dig_in_nid
) {
1470 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_digital_capture
);
1471 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
1478 static void alc_free(struct hda_codec
*codec
)
1485 static struct hda_codec_ops alc_patch_ops
= {
1486 .build_controls
= alc_build_controls
,
1487 .build_pcms
= alc_build_pcms
,
1491 .resume
= alc_resume
,
1497 * Test configuration for debugging
1499 * Almost all inputs/outputs are enabled. I/O pins can be configured via
1502 #ifdef CONFIG_SND_DEBUG
1503 static hda_nid_t alc880_test_dac_nids
[4] = {
1504 0x02, 0x03, 0x04, 0x05
1507 static struct hda_input_mux alc880_test_capture_source
= {
1518 static struct alc_channel_mode alc880_test_modes
[4] = {
1525 static int alc_test_pin_ctl_info(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_info_t
*uinfo
)
1527 static char *texts
[] = {
1528 "N/A", "Line Out", "HP Out",
1529 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1531 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1533 uinfo
->value
.enumerated
.items
= 8;
1534 if (uinfo
->value
.enumerated
.item
>= 8)
1535 uinfo
->value
.enumerated
.item
= 7;
1536 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1540 static int alc_test_pin_ctl_get(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
1542 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1543 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1544 unsigned int pin_ctl
, item
= 0;
1546 pin_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1547 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1548 if (pin_ctl
& AC_PINCTL_OUT_EN
) {
1549 if (pin_ctl
& AC_PINCTL_HP_EN
)
1553 } else if (pin_ctl
& AC_PINCTL_IN_EN
) {
1554 switch (pin_ctl
& AC_PINCTL_VREFEN
) {
1555 case AC_PINCTL_VREF_HIZ
: item
= 3; break;
1556 case AC_PINCTL_VREF_50
: item
= 4; break;
1557 case AC_PINCTL_VREF_GRD
: item
= 5; break;
1558 case AC_PINCTL_VREF_80
: item
= 6; break;
1559 case AC_PINCTL_VREF_100
: item
= 7; break;
1562 ucontrol
->value
.enumerated
.item
[0] = item
;
1566 static int alc_test_pin_ctl_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
1568 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1569 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1570 static unsigned int ctls
[] = {
1571 0, AC_PINCTL_OUT_EN
, AC_PINCTL_OUT_EN
| AC_PINCTL_HP_EN
,
1572 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_HIZ
,
1573 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_50
,
1574 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_GRD
,
1575 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_80
,
1576 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_100
,
1578 unsigned int old_ctl
, new_ctl
;
1580 old_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1581 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1582 new_ctl
= ctls
[ucontrol
->value
.enumerated
.item
[0]];
1583 if (old_ctl
!= new_ctl
) {
1584 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, new_ctl
);
1585 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
1586 ucontrol
->value
.enumerated
.item
[0] >= 3 ? 0xb080 : 0xb000);
1592 static int alc_test_pin_src_info(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_info_t
*uinfo
)
1594 static char *texts
[] = {
1595 "Front", "Surround", "CLFE", "Side"
1597 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1599 uinfo
->value
.enumerated
.items
= 4;
1600 if (uinfo
->value
.enumerated
.item
>= 4)
1601 uinfo
->value
.enumerated
.item
= 3;
1602 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1606 static int alc_test_pin_src_get(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
1608 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1609 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1612 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1613 ucontrol
->value
.enumerated
.item
[0] = sel
& 3;
1617 static int alc_test_pin_src_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
1619 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1620 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1623 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0) & 3;
1624 if (ucontrol
->value
.enumerated
.item
[0] != sel
) {
1625 sel
= ucontrol
->value
.enumerated
.item
[0] & 3;
1626 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_CONNECT_SEL
, sel
);
1632 #define PIN_CTL_TEST(xname,nid) { \
1633 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1635 .info = alc_test_pin_ctl_info, \
1636 .get = alc_test_pin_ctl_get, \
1637 .put = alc_test_pin_ctl_put, \
1638 .private_value = nid \
1641 #define PIN_SRC_TEST(xname,nid) { \
1642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1644 .info = alc_test_pin_src_info, \
1645 .get = alc_test_pin_src_get, \
1646 .put = alc_test_pin_src_put, \
1647 .private_value = nid \
1650 static snd_kcontrol_new_t alc880_test_mixer
[] = {
1651 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
1652 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
1653 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT
),
1654 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
1655 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
1656 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
1657 ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT
),
1658 ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT
),
1659 PIN_CTL_TEST("Front Pin Mode", 0x14),
1660 PIN_CTL_TEST("Surround Pin Mode", 0x15),
1661 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1662 PIN_CTL_TEST("Side Pin Mode", 0x17),
1663 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1664 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1665 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1666 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1667 PIN_SRC_TEST("In-1 Pin Source", 0x18),
1668 PIN_SRC_TEST("In-2 Pin Source", 0x19),
1669 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1670 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1671 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT
),
1672 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT
),
1673 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT
),
1674 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT
),
1675 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT
),
1676 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT
),
1677 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT
),
1678 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT
),
1679 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT
),
1680 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT
),
1681 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
1682 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
1683 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
1684 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
1686 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1687 .name
= "Input Source",
1689 .info
= alc_mux_enum_info
,
1690 .get
= alc_mux_enum_get
,
1691 .put
= alc_mux_enum_put
,
1694 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1695 .name
= "Channel Mode",
1696 .info
= alc880_ch_mode_info
,
1697 .get
= alc880_ch_mode_get
,
1698 .put
= alc880_ch_mode_put
,
1703 static struct hda_verb alc880_test_init_verbs
[] = {
1704 /* Unmute inputs of 0x0c - 0x0f */
1705 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1706 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1707 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1708 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1709 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1710 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1711 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1712 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1713 /* Vol output for 0x0c-0x0f */
1714 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1715 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1716 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1717 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1718 /* Set output pins 0x14-0x17 */
1719 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1720 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1721 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1722 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1723 /* Unmute output pins 0x14-0x17 */
1724 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1725 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1726 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1727 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1728 /* Set input pins 0x18-0x1c */
1729 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1730 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1731 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1732 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1733 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1734 /* Mute input pins 0x18-0x1b */
1735 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1736 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1737 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1738 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1740 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1741 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
1742 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1743 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
1744 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1745 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
1746 /* Analog input/passthru */
1747 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1748 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1749 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1750 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1751 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1759 static struct hda_board_config alc880_cfg_tbl
[] = {
1760 /* Back 3 jack, front 2 jack */
1761 { .modelname
= "3stack", .config
= ALC880_3ST
},
1762 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe200, .config
= ALC880_3ST
},
1763 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe201, .config
= ALC880_3ST
},
1764 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe202, .config
= ALC880_3ST
},
1765 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe203, .config
= ALC880_3ST
},
1766 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe204, .config
= ALC880_3ST
},
1767 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe205, .config
= ALC880_3ST
},
1768 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe206, .config
= ALC880_3ST
},
1769 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe207, .config
= ALC880_3ST
},
1770 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe208, .config
= ALC880_3ST
},
1771 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe209, .config
= ALC880_3ST
},
1772 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20a, .config
= ALC880_3ST
},
1773 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20b, .config
= ALC880_3ST
},
1774 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20c, .config
= ALC880_3ST
},
1775 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20d, .config
= ALC880_3ST
},
1776 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20e, .config
= ALC880_3ST
},
1777 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20f, .config
= ALC880_3ST
},
1778 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe210, .config
= ALC880_3ST
},
1779 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe211, .config
= ALC880_3ST
},
1780 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe214, .config
= ALC880_3ST
},
1781 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe302, .config
= ALC880_3ST
},
1782 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe303, .config
= ALC880_3ST
},
1783 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe304, .config
= ALC880_3ST
},
1784 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe306, .config
= ALC880_3ST
},
1785 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe307, .config
= ALC880_3ST
},
1786 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe404, .config
= ALC880_3ST
},
1787 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa101, .config
= ALC880_3ST
},
1788 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3031, .config
= ALC880_3ST
},
1789 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4036, .config
= ALC880_3ST
},
1790 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4037, .config
= ALC880_3ST
},
1791 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4038, .config
= ALC880_3ST
},
1792 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4040, .config
= ALC880_3ST
},
1793 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4041, .config
= ALC880_3ST
},
1795 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1796 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe310, .config
= ALC880_3ST
},
1797 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81d6, .config
= ALC880_3ST
},
1799 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1800 { .modelname
= "3stack-digout", .config
= ALC880_3ST_DIG
},
1801 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe308, .config
= ALC880_3ST_DIG
},
1803 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1804 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe305, .config
= ALC880_3ST_DIG
},
1805 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd402, .config
= ALC880_3ST_DIG
},
1806 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe309, .config
= ALC880_3ST_DIG
},
1808 /* Back 5 jack, front 2 jack */
1809 { .modelname
= "5stack", .config
= ALC880_5ST
},
1810 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3033, .config
= ALC880_5ST
},
1811 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4039, .config
= ALC880_5ST
},
1812 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3032, .config
= ALC880_5ST
},
1813 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x2a09, .config
= ALC880_5ST
},
1814 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x814e, .config
= ALC880_5ST
},
1816 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1817 { .modelname
= "5stack-digout", .config
= ALC880_5ST_DIG
},
1818 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe224, .config
= ALC880_5ST_DIG
},
1819 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe400, .config
= ALC880_5ST_DIG
},
1820 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe401, .config
= ALC880_5ST_DIG
},
1821 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe402, .config
= ALC880_5ST_DIG
},
1822 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd400, .config
= ALC880_5ST_DIG
},
1823 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd401, .config
= ALC880_5ST_DIG
},
1824 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa100, .config
= ALC880_5ST_DIG
},
1825 { .pci_subvendor
= 0x1565, .pci_subdevice
= 0x8202, .config
= ALC880_5ST_DIG
},
1826 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa880, .config
= ALC880_5ST_DIG
},
1827 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa884, .config
= ALC880_5ST_DIG
},
1828 { .pci_subvendor
= 0x1695, .pci_subdevice
= 0x400d, .config
= ALC880_5ST_DIG
},
1829 { .pci_subvendor
= 0x0000, .pci_subdevice
= 0x8086, .config
= ALC880_5ST_DIG
},
1831 { .modelname
= "w810", .config
= ALC880_W810
},
1832 { .pci_subvendor
= 0x161f, .pci_subdevice
= 0x203d, .config
= ALC880_W810
},
1834 { .modelname
= "z71v", .config
= ALC880_Z71V
},
1835 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_Z71V
},
1837 { .modelname
= "6statack-digout", .config
= ALC880_6ST_DIG
},
1838 { .pci_subvendor
= 0x2668, .pci_subdevice
= 0x8086, .config
= ALC880_6ST_DIG
},
1839 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0x2668, .config
= ALC880_6ST_DIG
},
1840 { .pci_subvendor
= 0x1462, .pci_subdevice
= 0x1150, .config
= ALC880_6ST_DIG
},
1841 { .pci_subvendor
= 0xe803, .pci_subdevice
= 0x1019, .config
= ALC880_6ST_DIG
},
1843 { .modelname
= "asua", .config
= ALC880_ASUS
},
1844 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_ASUS_DIG
},
1845 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1973, .config
= ALC880_ASUS_DIG
},
1846 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x19b3, .config
= ALC880_ASUS_DIG
},
1847 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1113, .config
= ALC880_ASUS_DIG
},
1848 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1993, .config
= ALC880_ASUS
},
1849 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10c3, .config
= ALC880_ASUS_DIG
},
1850 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1133, .config
= ALC880_ASUS
},
1851 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1123, .config
= ALC880_ASUS_DIG
},
1852 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1143, .config
= ALC880_ASUS
},
1853 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10b3, .config
= ALC880_ASUS_W1V
},
1855 { .modelname
= "uniwill", .config
= ALC880_UNIWILL_DIG
},
1856 { .pci_subvendor
= 0x1584, .pci_subdevice
= 0x9050, .config
= ALC880_UNIWILL_DIG
},
1858 { .modelname
= "F1734", .config
= ALC880_F1734
},
1859 { .pci_subvendor
= 0x1734, .pci_subdevice
= 0x107c, .config
= ALC880_F1734
},
1861 #ifdef CONFIG_SND_DEBUG
1862 { .modelname
= "test", .config
= ALC880_TEST
},
1869 * configuration template - to be copied to the spec instance
1871 struct alc_config_preset
{
1872 snd_kcontrol_new_t
*mixers
;
1873 unsigned int front_panel
: 1; /* optional */
1874 unsigned int gpio_payload
; /* optional */
1875 struct hda_verb
*init_verbs
;
1876 unsigned int num_dacs
;
1877 hda_nid_t
*dac_nids
;
1878 hda_nid_t dig_out_nid
; /* optional */
1879 hda_nid_t hp_nid
; /* optional */
1880 unsigned int num_adc_nids
;
1881 hda_nid_t
*adc_nids
;
1882 unsigned int num_channel_mode
;
1883 const struct alc_channel_mode
*channel_mode
;
1884 const struct hda_input_mux
*input_mux
;
1887 static struct alc_config_preset alc880_presets
[] = {
1889 .mixers
= alc880_base_mixer
,
1890 .init_verbs
= alc880_init_verbs_three_stack
,
1891 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1893 .dac_nids
= alc880_dac_nids
,
1895 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1896 .adc_nids
= alc880_adc_nids
,
1897 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1898 .channel_mode
= alc880_threestack_modes
,
1899 .input_mux
= &alc880_capture_source
,
1901 [ALC880_3ST_DIG
] = {
1902 .mixers
= alc880_base_mixer
,
1903 .init_verbs
= alc880_init_verbs_three_stack
,
1904 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1906 .dac_nids
= alc880_dac_nids
,
1907 .dig_out_nid
= ALC880_DIGOUT_NID
,
1909 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1910 .adc_nids
= alc880_adc_nids
,
1911 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1912 .channel_mode
= alc880_threestack_modes
,
1913 .input_mux
= &alc880_capture_source
,
1916 .mixers
= alc880_five_stack_mixer
,
1917 .init_verbs
= alc880_init_verbs_five_stack
,
1919 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1920 .dac_nids
= alc880_dac_nids
,
1922 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1923 .adc_nids
= alc880_adc_nids
,
1924 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1925 .channel_mode
= alc880_fivestack_modes
,
1926 .input_mux
= &alc880_capture_source
,
1928 [ALC880_5ST_DIG
] = {
1929 .mixers
= alc880_five_stack_mixer
,
1930 .init_verbs
= alc880_init_verbs_five_stack
,
1932 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1933 .dac_nids
= alc880_dac_nids
,
1934 .dig_out_nid
= ALC880_DIGOUT_NID
,
1936 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1937 .adc_nids
= alc880_adc_nids
,
1938 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1939 .channel_mode
= alc880_fivestack_modes
,
1940 .input_mux
= &alc880_capture_source
,
1942 [ALC880_6ST_DIG
] = {
1943 .mixers
= alc880_six_stack_mixer
,
1944 .init_verbs
= alc880_six_stack_init_verbs
,
1946 .num_dacs
= ARRAY_SIZE(alc880_6st_dac_nids
),
1947 .dac_nids
= alc880_6st_dac_nids
,
1948 .dig_out_nid
= ALC880_DIGOUT_NID
,
1949 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1950 .adc_nids
= alc880_adc_nids
,
1951 .num_channel_mode
= ARRAY_SIZE(alc880_sixstack_modes
),
1952 .channel_mode
= alc880_sixstack_modes
,
1953 .input_mux
= &alc880_6stack_capture_source
,
1956 .mixers
= alc880_w810_base_mixer
,
1957 .init_verbs
= alc880_w810_init_verbs
,
1958 .gpio_payload
= 0x2,
1959 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
1960 .dac_nids
= alc880_w810_dac_nids
,
1961 .dig_out_nid
= ALC880_DIGOUT_NID
,
1962 // No dedicated headphone socket - it's shared with built-in speakers.
1963 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1964 .adc_nids
= alc880_adc_nids
,
1965 .num_channel_mode
= ARRAY_SIZE(alc880_w810_modes
),
1966 .channel_mode
= alc880_w810_modes
,
1967 .input_mux
= &alc880_capture_source
,
1970 .mixers
= alc880_z71v_mixer
,
1971 .init_verbs
= alc880_z71v_init_verbs
,
1972 .num_dacs
= ARRAY_SIZE(alc880_z71v_dac_nids
),
1973 .dac_nids
= alc880_z71v_dac_nids
,
1974 .dig_out_nid
= ALC880_DIGOUT_NID
,
1976 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1977 .adc_nids
= alc880_adc_nids
,
1978 .num_channel_mode
= ARRAY_SIZE(alc880_z71v_modes
),
1979 .channel_mode
= alc880_z71v_modes
,
1980 .input_mux
= &alc880_capture_source
,
1983 .mixers
= alc880_2_jack_mixer
,
1984 .init_verbs
= alc880_2_jack_init_verbs
,
1985 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1986 .dac_nids
= alc880_dac_nids
,
1988 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
1989 .adc_nids
= alc880_adc_nids
,
1990 .num_channel_mode
= ARRAY_SIZE(alc880_z71v_modes
),
1991 .channel_mode
= alc880_z71v_modes
,
1992 .input_mux
= &alc880_capture_source
,
1995 .mixers
= alc880_asus_mixer
,
1996 .init_verbs
= alc880_asus_init_verbs
,
1997 .gpio_payload
= 0x1,
1999 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
2000 .dac_nids
= alc880_w810_dac_nids
,
2001 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
2002 .adc_nids
= alc880_adc_nids
,
2003 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
2004 .channel_mode
= alc880_threestack_modes
,
2005 .input_mux
= &alc880_capture_source
,
2007 [ALC880_ASUS_DIG
] = {
2008 .mixers
= alc880_asus_mixer
,
2009 .init_verbs
= alc880_asus_init_verbs
,
2010 .gpio_payload
= 0x1,
2012 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
2013 .dac_nids
= alc880_w810_dac_nids
,
2014 .dig_out_nid
= ALC880_DIGOUT_NID
,
2015 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
2016 .adc_nids
= alc880_adc_nids
,
2017 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
2018 .channel_mode
= alc880_threestack_modes
,
2019 .input_mux
= &alc880_capture_source
,
2021 [ALC880_ASUS_W1V
] = {
2022 .mixers
= alc880_asus_w1v_mixer
,
2023 .init_verbs
= alc880_asus_init_verbs
,
2024 .gpio_payload
= 0x1,
2026 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
2027 .dac_nids
= alc880_w810_dac_nids
,
2028 .dig_out_nid
= ALC880_DIGOUT_NID
,
2029 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
2030 .adc_nids
= alc880_adc_nids
,
2031 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
2032 .channel_mode
= alc880_threestack_modes
,
2033 .input_mux
= &alc880_capture_source
,
2035 [ALC880_UNIWILL_DIG
] = {
2036 .mixers
= alc880_asus_mixer
,
2037 .init_verbs
= alc880_asus_init_verbs
,
2038 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
2039 .dac_nids
= alc880_dac_nids
,
2040 .dig_out_nid
= ALC880_DIGOUT_NID
,
2042 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
2043 .adc_nids
= alc880_adc_nids
,
2044 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
2045 .channel_mode
= alc880_threestack_modes
,
2046 .input_mux
= &alc880_capture_source
,
2048 #ifdef CONFIG_SND_DEBUG
2050 .mixers
= alc880_test_mixer
,
2051 .init_verbs
= alc880_test_init_verbs
,
2052 .num_dacs
= ARRAY_SIZE(alc880_test_dac_nids
),
2053 .dac_nids
= alc880_test_dac_nids
,
2054 .dig_out_nid
= ALC880_DIGOUT_NID
,
2055 .num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
),
2056 .adc_nids
= alc880_adc_nids
,
2057 .num_channel_mode
= ARRAY_SIZE(alc880_test_modes
),
2058 .channel_mode
= alc880_test_modes
,
2059 .input_mux
= &alc880_test_capture_source
,
2064 static int patch_alc880(struct hda_codec
*codec
)
2066 struct alc_spec
*spec
;
2068 const struct alc_config_preset
*preset
;
2070 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
2074 init_MUTEX(&spec
->bind_mutex
);
2077 board_config
= snd_hda_check_board_config(codec
, alc880_cfg_tbl
);
2078 if (board_config
< 0 || board_config
>= ALC880_MODEL_LAST
) {
2079 snd_printd(KERN_INFO
"hda_codec: Unknown model for ALC880\n");
2080 board_config
= ALC880_3ST
;
2082 preset
= &alc880_presets
[board_config
];
2084 spec
->mixers
[spec
->num_mixers
] = preset
->mixers
;
2085 snd_assert(spec
->mixers
[0], kfree(spec
);return -EINVAL
);
2088 /* some MBs need GPIO setup */
2089 if (preset
->gpio_payload
) {
2090 /* Enable mask and set output */
2091 snd_hda_codec_write(codec
, codec
->afg
, 0,
2092 AC_VERB_SET_GPIO_MASK
, preset
->gpio_payload
);
2093 snd_hda_codec_write(codec
, codec
->afg
, 0,
2094 AC_VERB_SET_GPIO_DIRECTION
, preset
->gpio_payload
);
2095 snd_hda_codec_write(codec
, codec
->afg
, 0,
2096 AC_VERB_SET_GPIO_DATA
, preset
->gpio_payload
);
2099 spec
->front_panel
= preset
->front_panel
;
2100 spec
->init_verbs
= preset
->init_verbs
;
2101 spec
->channel_mode
= preset
->channel_mode
;
2102 spec
->num_channel_mode
= preset
->num_channel_mode
;
2104 spec
->stream_name_analog
= "ALC880 Analog";
2105 spec
->stream_analog_playback
= &alc880_pcm_analog_playback
;
2106 spec
->stream_analog_capture
= &alc880_pcm_analog_capture
;
2108 spec
->stream_name_digital
= "ALC880 Digital";
2109 spec
->stream_digital_playback
= &alc880_pcm_digital_playback
;
2110 spec
->stream_digital_capture
= &alc880_pcm_digital_capture
;
2112 spec
->multiout
.max_channels
= spec
->channel_mode
[0].channels
;
2114 spec
->multiout
.num_dacs
= preset
->num_dacs
;
2115 spec
->multiout
.dac_nids
= preset
->adc_nids
;
2116 spec
->multiout
.dig_out_nid
= preset
->dig_out_nid
;
2117 spec
->multiout
.hp_nid
= preset
->hp_nid
;
2119 spec
->input_mux
= preset
->input_mux
;
2120 spec
->num_adc_nids
= preset
->num_adc_nids
;
2121 spec
->adc_nids
= preset
->adc_nids
;
2123 codec
->patch_ops
= alc_patch_ops
;
2133 * This is just place-holder, so there's something for alc_build_pcms to look
2134 * at when it calculates the maximum number of channels. ALC260 has no mixer
2135 * element which allows changing the channel mode, so the verb list is
2138 static struct alc_channel_mode alc260_modes
[1] = {
2142 snd_kcontrol_new_t alc260_base_mixer
[] = {
2143 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2144 ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT
),
2145 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2146 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2147 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT
),
2148 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT
),
2149 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT
),
2150 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT
),
2151 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT
),
2152 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT
),
2153 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT
),
2154 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT
),
2155 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2156 ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT
),
2157 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2158 ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT
),
2159 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT
),
2160 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT
),
2162 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2163 .name
= "Capture Source",
2164 .info
= alc_mux_enum_info
,
2165 .get
= alc_mux_enum_get
,
2166 .put
= alc_mux_enum_put
,
2171 snd_kcontrol_new_t alc260_hp_mixer
[] = {
2172 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2173 ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT
),
2174 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2175 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2176 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT
),
2177 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT
),
2178 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT
),
2179 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT
),
2180 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT
),
2181 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT
),
2182 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2183 ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT
),
2184 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2185 ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT
),
2186 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT
),
2187 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT
),
2189 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2190 .name
= "Capture Source",
2191 .info
= alc_mux_enum_info
,
2192 .get
= alc_mux_enum_get
,
2193 .put
= alc_mux_enum_put
,
2198 static struct hda_verb alc260_init_verbs
[] = {
2199 /* Line In pin widget for input */
2200 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2201 /* CD pin widget for input */
2202 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2203 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2204 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2205 /* Mic2 (front panel) pin widget for input and vref at 80% */
2206 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2207 /* LINE-2 is used for line-out in rear */
2208 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2209 /* select line-out */
2210 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x00},
2212 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2214 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2216 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2217 /* mute capture amp left and right */
2218 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2219 /* set connection select to line in (default select for this ADC) */
2220 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2221 /* mute capture amp left and right */
2222 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2223 /* set connection select to line in (default select for this ADC) */
2224 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x02},
2225 /* set vol=0 Line-Out mixer amp left and right */
2226 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2227 /* unmute pin widget amp left and right (no gain on this amp) */
2228 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2229 /* set vol=0 HP mixer amp left and right */
2230 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2231 /* unmute pin widget amp left and right (no gain on this amp) */
2232 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2233 /* set vol=0 Mono mixer amp left and right */
2234 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2235 /* unmute pin widget amp left and right (no gain on this amp) */
2236 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2237 /* unmute LINE-2 out pin */
2238 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2239 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2241 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
2243 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
2245 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2246 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2247 /* mute Front out path */
2248 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2249 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2250 /* mute Headphone out path */
2251 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2252 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2253 /* mute Mono out path */
2254 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2255 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2259 static struct hda_pcm_stream alc260_pcm_analog_playback
= {
2266 static struct hda_pcm_stream alc260_pcm_analog_capture
= {
2273 static struct hda_board_config alc260_cfg_tbl
[] = {
2274 { .modelname
= "hp", .config
= ALC260_HP
},
2275 { .pci_subvendor
= 0x103c, .config
= ALC260_HP
},
2279 static int patch_alc260(struct hda_codec
*codec
)
2281 struct alc_spec
*spec
;
2284 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
2288 init_MUTEX(&spec
->bind_mutex
);
2291 board_config
= snd_hda_check_board_config(codec
, alc260_cfg_tbl
);
2292 if (board_config
< 0 || board_config
>= ALC260_MODEL_LAST
) {
2293 snd_printd(KERN_INFO
"hda_codec: Unknown model for ALC260\n");
2294 board_config
= ALC260_BASIC
;
2297 switch (board_config
) {
2299 spec
->mixers
[spec
->num_mixers
] = alc260_base_mixer
;
2303 spec
->mixers
[spec
->num_mixers
] = alc260_base_mixer
;
2308 spec
->init_verbs
= alc260_init_verbs
;
2309 spec
->channel_mode
= alc260_modes
;
2310 spec
->num_channel_mode
= ARRAY_SIZE(alc260_modes
);
2312 spec
->stream_name_analog
= "ALC260 Analog";
2313 spec
->stream_analog_playback
= &alc260_pcm_analog_playback
;
2314 spec
->stream_analog_capture
= &alc260_pcm_analog_capture
;
2316 spec
->multiout
.max_channels
= spec
->channel_mode
[0].channels
;
2317 spec
->multiout
.num_dacs
= ARRAY_SIZE(alc260_dac_nids
);
2318 spec
->multiout
.dac_nids
= alc260_dac_nids
;
2320 spec
->input_mux
= &alc260_capture_source
;
2321 switch (board_config
) {
2323 spec
->stream_analog_capture
->nid
= 5;
2324 spec
->num_adc_nids
= ARRAY_SIZE(alc260_hp_adc_nids
);
2325 spec
->adc_nids
= alc260_hp_adc_nids
;
2328 spec
->num_adc_nids
= ARRAY_SIZE(alc260_adc_nids
);
2329 spec
->adc_nids
= alc260_adc_nids
;
2333 codec
->patch_ops
= alc_patch_ops
;
2341 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
2342 * configuration. Each pin widget can choose any input DACs and a mixer.
2343 * Each ADC is connected from a mixer of all inputs. This makes possible
2344 * 6-channel independent captures.
2346 * In addition, an independent DAC for the multi-playback (not used in this
2350 static struct alc_channel_mode alc882_ch_modes
[1] = {
2354 static hda_nid_t alc882_dac_nids
[4] = {
2355 /* front, rear, clfe, rear_surr */
2356 0x02, 0x03, 0x04, 0x05
2359 static hda_nid_t alc882_adc_nids
[3] = {
2365 /* FIXME: should be a matrix-type input source selection */
2367 static struct hda_input_mux alc882_capture_source
= {
2371 { "Front Mic", 0x1 },
2377 #define alc882_mux_enum_info alc_mux_enum_info
2378 #define alc882_mux_enum_get alc_mux_enum_get
2380 static int alc882_mux_enum_put(snd_kcontrol_t
*kcontrol
, snd_ctl_elem_value_t
*ucontrol
)
2382 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
2383 struct alc_spec
*spec
= codec
->spec
;
2384 const struct hda_input_mux
*imux
= spec
->input_mux
;
2385 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
2386 static hda_nid_t capture_mixers
[3] = { 0x24, 0x23, 0x22 };
2387 hda_nid_t nid
= capture_mixers
[adc_idx
];
2388 unsigned int *cur_val
= &spec
->cur_mux
[adc_idx
];
2389 unsigned int i
, idx
;
2391 idx
= ucontrol
->value
.enumerated
.item
[0];
2392 if (idx
>= imux
->num_items
)
2393 idx
= imux
->num_items
- 1;
2394 if (*cur_val
== idx
&& ! codec
->in_resume
)
2396 for (i
= 0; i
< imux
->num_items
; i
++) {
2397 unsigned int v
= (i
== idx
) ? 0x7000 : 0x7080;
2398 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
2399 v
| (imux
->items
[i
].index
<< 8));
2405 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
2406 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
2408 static snd_kcontrol_new_t alc882_base_mixer
[] = {
2409 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
2410 ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
2411 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
2412 ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
2413 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
2414 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
2415 ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
2416 ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT
),
2417 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
2418 ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
2419 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
2420 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
2421 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
2422 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
2423 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
2424 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
2425 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
2426 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
2427 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
2428 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
2429 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
2430 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
2431 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
2432 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
2433 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
2434 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
2435 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
2437 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2438 /* .name = "Capture Source", */
2439 .name
= "Input Source",
2441 .info
= alc882_mux_enum_info
,
2442 .get
= alc882_mux_enum_get
,
2443 .put
= alc882_mux_enum_put
,
2448 static struct hda_verb alc882_init_verbs
[] = {
2449 /* Front mixer: unmute input/output amp left and right (volume = 0) */
2450 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2451 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2452 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2454 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2455 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2456 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2458 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2459 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2460 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2462 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2463 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2464 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2466 /* Front Pin: to output mode */
2467 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2468 /* Front Pin: mute amp left and right (no volume) */
2469 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2470 /* select Front mixer (0x0c, index 0) */
2471 {0x14, AC_VERB_SET_CONNECT_SEL
, 0x00},
2473 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2474 /* Rear Pin: mute amp left and right (no volume) */
2475 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2476 /* select Rear mixer (0x0d, index 1) */
2477 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x01},
2479 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2480 /* CLFE Pin: mute amp left and right (no volume) */
2481 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2482 /* select CLFE mixer (0x0e, index 2) */
2483 {0x16, AC_VERB_SET_CONNECT_SEL
, 0x02},
2485 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2486 /* Side Pin: mute amp left and right (no volume) */
2487 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2488 /* select Side mixer (0x0f, index 3) */
2489 {0x17, AC_VERB_SET_CONNECT_SEL
, 0x03},
2491 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2492 /* Headphone Pin: mute amp left and right (no volume) */
2493 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2494 /* select Front mixer (0x0c, index 0) */
2495 {0x1b, AC_VERB_SET_CONNECT_SEL
, 0x00},
2496 /* Mic (rear) pin widget for input and vref at 80% */
2497 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2498 /* Front Mic pin widget for input and vref at 80% */
2499 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2500 /* Line In pin widget for input */
2501 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2502 /* CD pin widget for input */
2503 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2505 /* FIXME: use matrix-type input source selection */
2506 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
2507 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
2508 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2509 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2510 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2511 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2513 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2514 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2515 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2516 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2518 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2519 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
2520 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
2521 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
2522 /* ADC1: mute amp left and right */
2523 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2524 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
2525 /* ADC2: mute amp left and right */
2526 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2527 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
2528 /* ADC3: mute amp left and right */
2529 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2530 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
2535 static int patch_alc882(struct hda_codec
*codec
)
2537 struct alc_spec
*spec
;
2539 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
2543 init_MUTEX(&spec
->bind_mutex
);
2546 spec
->mixers
[spec
->num_mixers
] = alc882_base_mixer
;
2549 spec
->multiout
.dig_out_nid
= ALC880_DIGOUT_NID
;
2550 spec
->dig_in_nid
= ALC880_DIGIN_NID
;
2551 spec
->front_panel
= 1;
2552 spec
->init_verbs
= alc882_init_verbs
;
2553 spec
->channel_mode
= alc882_ch_modes
;
2554 spec
->num_channel_mode
= ARRAY_SIZE(alc882_ch_modes
);
2556 spec
->stream_name_analog
= "ALC882 Analog";
2557 spec
->stream_analog_playback
= &alc880_pcm_analog_playback
;
2558 spec
->stream_analog_capture
= &alc880_pcm_analog_capture
;
2560 spec
->stream_name_digital
= "ALC882 Digital";
2561 spec
->stream_digital_playback
= &alc880_pcm_digital_playback
;
2562 spec
->stream_digital_capture
= &alc880_pcm_digital_capture
;
2564 spec
->multiout
.max_channels
= spec
->channel_mode
[0].channels
;
2565 spec
->multiout
.num_dacs
= ARRAY_SIZE(alc882_dac_nids
);
2566 spec
->multiout
.dac_nids
= alc882_dac_nids
;
2568 spec
->input_mux
= &alc882_capture_source
;
2569 spec
->num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
);
2570 spec
->adc_nids
= alc882_adc_nids
;
2572 codec
->patch_ops
= alc_patch_ops
;
2580 struct hda_codec_preset snd_hda_preset_realtek
[] = {
2581 { .id
= 0x10ec0260, .name
= "ALC260", .patch
= patch_alc260
},
2582 { .id
= 0x10ec0880, .name
= "ALC880", .patch
= patch_alc880
},
2583 { .id
= 0x10ec0882, .name
= "ALC882", .patch
= patch_alc882
},