2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for ALC 260/880/882 codecs
6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
8 * Takashi Iwai <tiwai@suse.de>
10 * This driver is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This driver is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sound/driver.h>
26 #include <linux/init.h>
27 #include <linux/delay.h>
28 #include <linux/slab.h>
29 #include <linux/pci.h>
30 #include <sound/core.h>
31 #include "hda_codec.h"
32 #include "hda_local.h"
35 /* ALC880 board config type */
53 #ifdef CONFIG_SND_DEBUG
57 ALC880_MODEL_LAST
/* last tag */
67 ALC260_MODEL_LAST
/* last tag */
74 ALC262_MODEL_LAST
/* last tag */
95 #define GPIO_MASK 0x03
98 /* codec parameterization */
99 struct snd_kcontrol_new
*mixers
[5]; /* mixer arrays */
100 unsigned int num_mixers
;
102 const struct hda_verb
*init_verbs
[5]; /* initialization verbs
103 * don't forget NULL termination!
105 unsigned int num_init_verbs
;
107 char *stream_name_analog
; /* analog PCM stream */
108 struct hda_pcm_stream
*stream_analog_playback
;
109 struct hda_pcm_stream
*stream_analog_capture
;
111 char *stream_name_digital
; /* digital PCM stream */
112 struct hda_pcm_stream
*stream_digital_playback
;
113 struct hda_pcm_stream
*stream_digital_capture
;
116 struct hda_multi_out multiout
; /* playback set-up
117 * max_channels, dacs must be set
118 * dig_out_nid and hp_nid are optional
122 unsigned int num_adc_nids
;
124 hda_nid_t dig_in_nid
; /* digital-in NID; optional */
127 const struct hda_input_mux
*input_mux
;
128 unsigned int cur_mux
[3];
131 const struct hda_channel_mode
*channel_mode
;
132 int num_channel_mode
;
134 /* PCM information */
135 struct hda_pcm pcm_rec
[3]; /* used in alc_build_pcms() */
137 /* dynamic controls, init_verbs and input_mux */
138 struct auto_pin_cfg autocfg
;
139 unsigned int num_kctl_alloc
, num_kctl_used
;
140 struct snd_kcontrol_new
*kctl_alloc
;
141 struct hda_input_mux private_imux
;
142 hda_nid_t private_dac_nids
[5];
146 * configuration template - to be copied to the spec instance
148 struct alc_config_preset
{
149 struct snd_kcontrol_new
*mixers
[5]; /* should be identical size with spec */
150 const struct hda_verb
*init_verbs
[5];
151 unsigned int num_dacs
;
153 hda_nid_t dig_out_nid
; /* optional */
154 hda_nid_t hp_nid
; /* optional */
155 unsigned int num_adc_nids
;
157 hda_nid_t dig_in_nid
;
158 unsigned int num_channel_mode
;
159 const struct hda_channel_mode
*channel_mode
;
160 const struct hda_input_mux
*input_mux
;
167 static int alc_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
169 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
170 struct alc_spec
*spec
= codec
->spec
;
171 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
174 static int alc_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
176 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
177 struct alc_spec
*spec
= codec
->spec
;
178 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
180 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
184 static int alc_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
186 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
187 struct alc_spec
*spec
= codec
->spec
;
188 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
189 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
190 spec
->adc_nids
[adc_idx
], &spec
->cur_mux
[adc_idx
]);
195 * channel mode setting
197 static int alc_ch_mode_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
199 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
200 struct alc_spec
*spec
= codec
->spec
;
201 return snd_hda_ch_mode_info(codec
, uinfo
, spec
->channel_mode
,
202 spec
->num_channel_mode
);
205 static int alc_ch_mode_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
207 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
208 struct alc_spec
*spec
= codec
->spec
;
209 return snd_hda_ch_mode_get(codec
, ucontrol
, spec
->channel_mode
,
210 spec
->num_channel_mode
, spec
->multiout
.max_channels
);
213 static int alc_ch_mode_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
215 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
216 struct alc_spec
*spec
= codec
->spec
;
217 return snd_hda_ch_mode_put(codec
, ucontrol
, spec
->channel_mode
,
218 spec
->num_channel_mode
, &spec
->multiout
.max_channels
);
222 * Control the mode of pin widget settings via the mixer. "pc" is used
223 * instead of "%" to avoid consequences of accidently treating the % as
224 * being part of a format specifier. Maximum allowed length of a value is
225 * 63 characters plus NULL terminator.
227 static char *alc_pin_mode_names
[] = {
228 "Line in", "Mic 80pc bias", "Mic 50pc bias",
229 "Line out", "Headphone out",
231 static unsigned char alc_pin_mode_values
[] = {
232 PIN_IN
, PIN_VREF80
, PIN_VREF50
, PIN_OUT
, PIN_HP
,
234 /* The control can present all 5 options, or it can limit the options based
235 * in the pin being assumed to be exclusively an input or an output pin.
237 #define ALC_PIN_DIR_IN 0x00
238 #define ALC_PIN_DIR_OUT 0x01
239 #define ALC_PIN_DIR_INOUT 0x02
241 /* Info about the pin modes supported by the three different pin directions.
242 * For each direction the minimum and maximum values are given.
244 static signed char alc_pin_mode_dir_info
[3][2] = {
245 { 0, 2 }, /* ALC_PIN_DIR_IN */
246 { 3, 4 }, /* ALC_PIN_DIR_OUT */
247 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
249 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
250 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
251 #define alc_pin_mode_n_items(_dir) \
252 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
254 static int alc_pin_mode_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
256 unsigned int item_num
= uinfo
->value
.enumerated
.item
;
257 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
259 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
261 uinfo
->value
.enumerated
.items
= alc_pin_mode_n_items(dir
);
263 if (item_num
<alc_pin_mode_min(dir
) || item_num
>alc_pin_mode_max(dir
))
264 item_num
= alc_pin_mode_min(dir
);
265 strcpy(uinfo
->value
.enumerated
.name
, alc_pin_mode_names
[item_num
]);
269 static int alc_pin_mode_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
272 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
273 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
274 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
275 long *valp
= ucontrol
->value
.integer
.value
;
276 unsigned int pinctl
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_PIN_WIDGET_CONTROL
,0x00);
278 /* Find enumerated value for current pinctl setting */
279 i
= alc_pin_mode_min(dir
);
280 while (alc_pin_mode_values
[i
]!=pinctl
&& i
<=alc_pin_mode_max(dir
))
282 *valp
= i
<=alc_pin_mode_max(dir
)?i
:alc_pin_mode_min(dir
);
286 static int alc_pin_mode_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
289 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
290 hda_nid_t nid
= kcontrol
->private_value
& 0xffff;
291 unsigned char dir
= (kcontrol
->private_value
>> 16) & 0xff;
292 long val
= *ucontrol
->value
.integer
.value
;
293 unsigned int pinctl
= snd_hda_codec_read(codec
,nid
,0,AC_VERB_GET_PIN_WIDGET_CONTROL
,0x00);
295 if (val
<alc_pin_mode_min(dir
) || val
>alc_pin_mode_max(dir
))
296 val
= alc_pin_mode_min(dir
);
298 change
= pinctl
!= alc_pin_mode_values
[val
];
300 snd_hda_codec_write(codec
,nid
,0,AC_VERB_SET_PIN_WIDGET_CONTROL
,
301 alc_pin_mode_values
[val
]);
305 #define ALC_PIN_MODE(xname, nid, dir) \
306 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
307 .info = alc_pin_mode_info, \
308 .get = alc_pin_mode_get, \
309 .put = alc_pin_mode_put, \
310 .private_value = nid | (dir<<16) }
313 * set up from the preset table
315 static void setup_preset(struct alc_spec
*spec
, const struct alc_config_preset
*preset
)
319 for (i
= 0; i
< ARRAY_SIZE(preset
->mixers
) && preset
->mixers
[i
]; i
++)
320 spec
->mixers
[spec
->num_mixers
++] = preset
->mixers
[i
];
321 for (i
= 0; i
< ARRAY_SIZE(preset
->init_verbs
) && preset
->init_verbs
[i
]; i
++)
322 spec
->init_verbs
[spec
->num_init_verbs
++] = preset
->init_verbs
[i
];
324 spec
->channel_mode
= preset
->channel_mode
;
325 spec
->num_channel_mode
= preset
->num_channel_mode
;
327 spec
->multiout
.max_channels
= spec
->channel_mode
[0].channels
;
329 spec
->multiout
.num_dacs
= preset
->num_dacs
;
330 spec
->multiout
.dac_nids
= preset
->dac_nids
;
331 spec
->multiout
.dig_out_nid
= preset
->dig_out_nid
;
332 spec
->multiout
.hp_nid
= preset
->hp_nid
;
334 spec
->input_mux
= preset
->input_mux
;
336 spec
->num_adc_nids
= preset
->num_adc_nids
;
337 spec
->adc_nids
= preset
->adc_nids
;
338 spec
->dig_in_nid
= preset
->dig_in_nid
;
342 * ALC880 3-stack model
344 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
345 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
349 static hda_nid_t alc880_dac_nids
[4] = {
350 /* front, rear, clfe, rear_surr */
351 0x02, 0x05, 0x04, 0x03
354 static hda_nid_t alc880_adc_nids
[3] = {
359 /* The datasheet says the node 0x07 is connected from inputs,
360 * but it shows zero connection in the real implementation on some devices.
361 * Note: this is a 915GAV bug, fixed on 915GLV
363 static hda_nid_t alc880_adc_nids_alt
[2] = {
368 #define ALC880_DIGOUT_NID 0x06
369 #define ALC880_DIGIN_NID 0x0a
371 static struct hda_input_mux alc880_capture_source
= {
375 { "Front Mic", 0x3 },
381 /* channel source setting (2/6 channel selection for 3-stack) */
383 static struct hda_verb alc880_threestack_ch2_init
[] = {
384 /* set line-in to input, mute it */
385 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
386 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
387 /* set mic-in to input vref 80%, mute it */
388 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
389 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
394 static struct hda_verb alc880_threestack_ch6_init
[] = {
395 /* set line-in to output, unmute it */
396 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
397 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
398 /* set mic-in to output, unmute it */
399 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
400 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
404 static struct hda_channel_mode alc880_threestack_modes
[2] = {
405 { 2, alc880_threestack_ch2_init
},
406 { 6, alc880_threestack_ch6_init
},
409 static struct snd_kcontrol_new alc880_three_stack_mixer
[] = {
410 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
411 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
412 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
413 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT
),
414 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
415 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
416 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
417 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
418 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
419 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
420 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
421 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
422 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
423 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
424 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT
),
425 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT
),
426 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
427 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
428 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT
),
430 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
431 .name
= "Channel Mode",
432 .info
= alc_ch_mode_info
,
433 .get
= alc_ch_mode_get
,
434 .put
= alc_ch_mode_put
,
439 /* capture mixer elements */
440 static struct snd_kcontrol_new alc880_capture_mixer
[] = {
441 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
442 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
443 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
444 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
445 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
446 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
448 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
449 /* The multiple "Capture Source" controls confuse alsamixer
450 * So call somewhat different..
451 * FIXME: the controls appear in the "playback" view!
453 /* .name = "Capture Source", */
454 .name
= "Input Source",
456 .info
= alc_mux_enum_info
,
457 .get
= alc_mux_enum_get
,
458 .put
= alc_mux_enum_put
,
463 /* capture mixer elements (in case NID 0x07 not available) */
464 static struct snd_kcontrol_new alc880_capture_alt_mixer
[] = {
465 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
466 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
467 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
468 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
470 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
471 /* The multiple "Capture Source" controls confuse alsamixer
472 * So call somewhat different..
473 * FIXME: the controls appear in the "playback" view!
475 /* .name = "Capture Source", */
476 .name
= "Input Source",
478 .info
= alc_mux_enum_info
,
479 .get
= alc_mux_enum_get
,
480 .put
= alc_mux_enum_put
,
488 * ALC880 5-stack model
490 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
491 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
492 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
495 /* additional mixers to alc880_three_stack_mixer */
496 static struct snd_kcontrol_new alc880_five_stack_mixer
[] = {
497 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
498 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT
),
502 /* channel source setting (6/8 channel selection for 5-stack) */
504 static struct hda_verb alc880_fivestack_ch6_init
[] = {
505 /* set line-in to input, mute it */
506 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
507 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
512 static struct hda_verb alc880_fivestack_ch8_init
[] = {
513 /* set line-in to output, unmute it */
514 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
515 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
519 static struct hda_channel_mode alc880_fivestack_modes
[2] = {
520 { 6, alc880_fivestack_ch6_init
},
521 { 8, alc880_fivestack_ch8_init
},
526 * ALC880 6-stack model
528 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
529 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
530 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
533 static hda_nid_t alc880_6st_dac_nids
[4] = {
534 /* front, rear, clfe, rear_surr */
535 0x02, 0x03, 0x04, 0x05
538 static struct hda_input_mux alc880_6stack_capture_source
= {
542 { "Front Mic", 0x1 },
548 /* fixed 8-channels */
549 static struct hda_channel_mode alc880_sixstack_modes
[1] = {
553 static struct snd_kcontrol_new alc880_six_stack_mixer
[] = {
554 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
555 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
556 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
557 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
558 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
559 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
560 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
561 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
562 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
563 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
564 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
565 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
566 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
567 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
568 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
569 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
570 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
571 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
572 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
573 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
575 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
576 .name
= "Channel Mode",
577 .info
= alc_ch_mode_info
,
578 .get
= alc_ch_mode_get
,
579 .put
= alc_ch_mode_put
,
588 * W810 has rear IO for:
591 * Center/LFE (DAC 04)
594 * The system also has a pair of internal speakers, and a headphone jack.
595 * These are both connected to Line2 on the codec, hence to DAC 02.
597 * There is a variable resistor to control the speaker or headphone
598 * volume. This is a hardware-only device without a software API.
600 * Plugging headphones in will disable the internal speakers. This is
601 * implemented in hardware, not via the driver using jack sense. In
602 * a similar fashion, plugging into the rear socket marked "front" will
603 * disable both the speakers and headphones.
605 * For input, there's a microphone jack, and an "audio in" jack.
606 * These may not do anything useful with this driver yet, because I
607 * haven't setup any initialization verbs for these yet...
610 static hda_nid_t alc880_w810_dac_nids
[3] = {
611 /* front, rear/surround, clfe */
615 /* fixed 6 channels */
616 static struct hda_channel_mode alc880_w810_modes
[1] = {
620 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
621 static struct snd_kcontrol_new alc880_w810_base_mixer
[] = {
622 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
623 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
624 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
625 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
626 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
627 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
628 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
629 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
630 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
638 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
639 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
642 static hda_nid_t alc880_z71v_dac_nids
[1] = {
645 #define ALC880_Z71V_HP_DAC 0x03
647 /* fixed 2 channels */
648 static struct hda_channel_mode alc880_2_jack_modes
[1] = {
652 static struct snd_kcontrol_new alc880_z71v_mixer
[] = {
653 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
654 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
655 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
656 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT
),
657 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
658 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
659 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
660 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
669 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
670 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
673 static hda_nid_t alc880_f1734_dac_nids
[1] = {
676 #define ALC880_F1734_HP_DAC 0x02
678 static struct snd_kcontrol_new alc880_f1734_mixer
[] = {
679 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
680 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT
),
681 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
682 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT
),
683 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
684 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
685 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
686 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
695 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
696 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
697 * Mic = 0x18, Line = 0x1a
700 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
701 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
703 static struct snd_kcontrol_new alc880_asus_mixer
[] = {
704 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
705 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
706 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
707 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
708 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
709 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
710 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
711 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 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("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
715 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
716 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
717 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
719 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
720 .name
= "Channel Mode",
721 .info
= alc_ch_mode_info
,
722 .get
= alc_ch_mode_get
,
723 .put
= alc_ch_mode_put
,
730 * ALC880 ASUS W1V model
732 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
733 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
734 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
737 /* additional mixers to alc880_asus_mixer */
738 static struct snd_kcontrol_new alc880_asus_w1v_mixer
[] = {
739 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT
),
740 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT
),
744 /* additional mixers to alc880_asus_mixer */
745 static struct snd_kcontrol_new alc880_pcbeep_mixer
[] = {
746 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
747 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
752 static struct snd_kcontrol_new alc880_tcl_s700_mixer
[] = {
753 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
754 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
755 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT
),
756 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT
),
757 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT
),
758 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT
),
759 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT
),
760 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
761 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
763 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
764 /* The multiple "Capture Source" controls confuse alsamixer
765 * So call somewhat different..
766 * FIXME: the controls appear in the "playback" view!
768 /* .name = "Capture Source", */
769 .name
= "Input Source",
771 .info
= alc_mux_enum_info
,
772 .get
= alc_mux_enum_get
,
773 .put
= alc_mux_enum_put
,
779 * build control elements
781 static int alc_build_controls(struct hda_codec
*codec
)
783 struct alc_spec
*spec
= codec
->spec
;
787 for (i
= 0; i
< spec
->num_mixers
; i
++) {
788 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
793 if (spec
->multiout
.dig_out_nid
) {
794 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
798 if (spec
->dig_in_nid
) {
799 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
808 * initialize the codec volumes, etc
812 * generic initialization of ADC, input mixers and output mixers
814 static struct hda_verb alc880_volume_init_verbs
[] = {
816 * Unmute ADC0-2 and set the default input to mic-in
818 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
819 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
820 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
821 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
822 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
823 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
825 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
827 * Note: PASD motherboards uses the Line In 2 as the input for front panel
830 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
831 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
832 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
833 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
834 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
835 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
838 * Set up output mixers (0x0c - 0x0f)
840 /* set vol=0 to output mixers */
841 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
842 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
843 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
844 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
845 /* set up input amps for analog loopback */
846 /* Amp Indices: DAC = 0, mixer = 1 */
847 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
848 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
849 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
850 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
851 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
852 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
853 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
854 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
860 * 3-stack pin configuration:
861 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
863 static struct hda_verb alc880_pin_3stack_init_verbs
[] = {
865 * preset connection lists of input pins
866 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
868 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02}, /* mic/clfe */
869 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
870 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x03}, /* line/surround */
873 * Set pin mode and muting
875 /* set front pin widgets 0x14 for output */
876 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
877 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
878 /* Mic1 (rear panel) pin widget for input and vref at 80% */
879 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
880 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
881 /* Mic2 (as headphone out) for HP output */
882 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
883 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
884 /* Line In pin widget for input */
885 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
886 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
887 /* Line2 (as front mic) pin widget for input and vref at 80% */
888 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
889 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
890 /* CD pin widget for input */
891 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
897 * 5-stack pin configuration:
898 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
899 * line-in/side = 0x1a, f-mic = 0x1b
901 static struct hda_verb alc880_pin_5stack_init_verbs
[] = {
903 * preset connection lists of input pins
904 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
906 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
907 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01}, /* line/side */
910 * Set pin mode and muting
912 /* set pin widgets 0x14-0x17 for output */
913 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
914 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
915 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
916 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
917 /* unmute pins for output (no gain on this amp) */
918 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
919 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
920 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
921 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
923 /* Mic1 (rear panel) pin widget for input and vref at 80% */
924 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
925 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
926 /* Mic2 (as headphone out) for HP output */
927 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
928 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
929 /* Line In pin widget for input */
930 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
931 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
932 /* Line2 (as front mic) pin widget for input and vref at 80% */
933 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
934 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
935 /* CD pin widget for input */
936 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
942 * W810 pin configuration:
943 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
945 static struct hda_verb alc880_pin_w810_init_verbs
[] = {
946 /* hphone/speaker input selector: front DAC */
947 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x0},
949 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
950 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
951 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
952 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
953 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
954 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
956 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
957 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
963 * Z71V pin configuration:
964 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
966 static struct hda_verb alc880_pin_z71v_init_verbs
[] = {
967 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
968 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
969 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
970 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
972 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
973 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
974 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
975 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
981 * 6-stack pin configuration:
982 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
983 * line = 0x1a, HP = 0x1b
985 static struct hda_verb alc880_pin_6stack_init_verbs
[] = {
986 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00}, /* HP */
988 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
989 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
990 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
991 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
992 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
993 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
994 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
995 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
997 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
998 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
999 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1000 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1001 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1002 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1003 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1004 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1005 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1012 * F1734 pin configuration:
1013 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1015 static struct hda_verb alc880_pin_f1734_init_verbs
[] = {
1016 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1017 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1018 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1019 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1021 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1022 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1023 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1024 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1026 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1027 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1028 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1029 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1031 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1032 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1033 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1034 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1041 * ASUS pin configuration:
1042 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1044 static struct hda_verb alc880_pin_asus_init_verbs
[] = {
1045 {0x10, AC_VERB_SET_CONNECT_SEL
, 0x02},
1046 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x00},
1047 {0x12, AC_VERB_SET_CONNECT_SEL
, 0x01},
1048 {0x13, AC_VERB_SET_CONNECT_SEL
, 0x00},
1050 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1051 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1052 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1053 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1054 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1055 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1056 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1057 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1059 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1060 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1061 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1062 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1063 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1064 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1065 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1066 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1067 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1072 /* Enable GPIO mask and set output */
1073 static struct hda_verb alc880_gpio1_init_verbs
[] = {
1074 {0x01, AC_VERB_SET_GPIO_MASK
, 0x01},
1075 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x01},
1076 {0x01, AC_VERB_SET_GPIO_DATA
, 0x01},
1081 /* Enable GPIO mask and set output */
1082 static struct hda_verb alc880_gpio2_init_verbs
[] = {
1083 {0x01, AC_VERB_SET_GPIO_MASK
, 0x02},
1084 {0x01, AC_VERB_SET_GPIO_DIRECTION
, 0x02},
1085 {0x01, AC_VERB_SET_GPIO_DATA
, 0x02},
1090 /* Clevo m520g init */
1091 static struct hda_verb alc880_pin_clevo_init_verbs
[] = {
1092 /* headphone output */
1093 {0x11, AC_VERB_SET_CONNECT_SEL
, 0x01},
1095 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1096 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1098 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1099 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1101 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1102 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1103 /* Mic1 (rear panel) */
1104 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1105 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1106 /* Mic2 (front panel) */
1107 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1108 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1110 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1111 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1112 /* change to EAPD mode */
1113 {0x20, AC_VERB_SET_COEF_INDEX
, 0x07},
1114 {0x20, AC_VERB_SET_PROC_COEF
, 0x3060},
1119 static struct hda_verb alc880_pin_tcl_S700_init_verbs
[] = {
1120 /* Headphone output */
1121 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
1123 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1124 {0x1b, AC_VERB_SET_CONNECT_SEL
, 0x00},
1126 /* Line In pin widget for input */
1127 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1128 /* CD pin widget for input */
1129 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1130 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1131 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1133 /* change to EAPD mode */
1134 {0x20, AC_VERB_SET_COEF_INDEX
, 0x07},
1135 {0x20, AC_VERB_SET_PROC_COEF
, 0x3070},
1143 static int alc_init(struct hda_codec
*codec
)
1145 struct alc_spec
*spec
= codec
->spec
;
1148 for (i
= 0; i
< spec
->num_init_verbs
; i
++)
1149 snd_hda_sequence_write(codec
, spec
->init_verbs
[i
]);
1157 static int alc_resume(struct hda_codec
*codec
)
1159 struct alc_spec
*spec
= codec
->spec
;
1163 for (i
= 0; i
< spec
->num_mixers
; i
++)
1164 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
1165 if (spec
->multiout
.dig_out_nid
)
1166 snd_hda_resume_spdif_out(codec
);
1167 if (spec
->dig_in_nid
)
1168 snd_hda_resume_spdif_in(codec
);
1175 * Analog playback callbacks
1177 static int alc880_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1178 struct hda_codec
*codec
,
1179 struct snd_pcm_substream
*substream
)
1181 struct alc_spec
*spec
= codec
->spec
;
1182 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
1185 static int alc880_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1186 struct hda_codec
*codec
,
1187 unsigned int stream_tag
,
1188 unsigned int format
,
1189 struct snd_pcm_substream
*substream
)
1191 struct alc_spec
*spec
= codec
->spec
;
1192 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
,
1196 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1197 struct hda_codec
*codec
,
1198 struct snd_pcm_substream
*substream
)
1200 struct alc_spec
*spec
= codec
->spec
;
1201 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
1207 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
1208 struct hda_codec
*codec
,
1209 struct snd_pcm_substream
*substream
)
1211 struct alc_spec
*spec
= codec
->spec
;
1212 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
1215 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
1216 struct hda_codec
*codec
,
1217 struct snd_pcm_substream
*substream
)
1219 struct alc_spec
*spec
= codec
->spec
;
1220 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
1226 static int alc880_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
1227 struct hda_codec
*codec
,
1228 unsigned int stream_tag
,
1229 unsigned int format
,
1230 struct snd_pcm_substream
*substream
)
1232 struct alc_spec
*spec
= codec
->spec
;
1234 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
1235 stream_tag
, 0, format
);
1239 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
1240 struct hda_codec
*codec
,
1241 struct snd_pcm_substream
*substream
)
1243 struct alc_spec
*spec
= codec
->spec
;
1245 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
], 0, 0, 0);
1252 static struct hda_pcm_stream alc880_pcm_analog_playback
= {
1256 /* NID is set in alc_build_pcms */
1258 .open
= alc880_playback_pcm_open
,
1259 .prepare
= alc880_playback_pcm_prepare
,
1260 .cleanup
= alc880_playback_pcm_cleanup
1264 static struct hda_pcm_stream alc880_pcm_analog_capture
= {
1268 /* NID is set in alc_build_pcms */
1270 .prepare
= alc880_capture_pcm_prepare
,
1271 .cleanup
= alc880_capture_pcm_cleanup
1275 static struct hda_pcm_stream alc880_pcm_digital_playback
= {
1279 /* NID is set in alc_build_pcms */
1281 .open
= alc880_dig_playback_pcm_open
,
1282 .close
= alc880_dig_playback_pcm_close
1286 static struct hda_pcm_stream alc880_pcm_digital_capture
= {
1290 /* NID is set in alc_build_pcms */
1293 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
1294 static struct hda_pcm_stream alc_pcm_null_playback
= {
1300 static int alc_build_pcms(struct hda_codec
*codec
)
1302 struct alc_spec
*spec
= codec
->spec
;
1303 struct hda_pcm
*info
= spec
->pcm_rec
;
1306 codec
->num_pcms
= 1;
1307 codec
->pcm_info
= info
;
1309 info
->name
= spec
->stream_name_analog
;
1310 if (spec
->stream_analog_playback
) {
1311 snd_assert(spec
->multiout
.dac_nids
, return -EINVAL
);
1312 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
1313 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
1315 if (spec
->stream_analog_capture
) {
1316 snd_assert(spec
->adc_nids
, return -EINVAL
);
1317 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
1318 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
1321 if (spec
->channel_mode
) {
1322 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= 0;
1323 for (i
= 0; i
< spec
->num_channel_mode
; i
++) {
1324 if (spec
->channel_mode
[i
].channels
> info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
) {
1325 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
= spec
->channel_mode
[i
].channels
;
1330 /* If the use of more than one ADC is requested for the current
1331 * model, configure a second analog capture-only PCM.
1333 if (spec
->num_adc_nids
> 1) {
1336 info
->name
= spec
->stream_name_analog
;
1337 /* No playback stream for second PCM */
1338 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = alc_pcm_null_playback
;
1339 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= 0;
1340 if (spec
->stream_analog_capture
) {
1341 snd_assert(spec
->adc_nids
, return -EINVAL
);
1342 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
1343 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[1];
1347 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
1350 info
->name
= spec
->stream_name_digital
;
1351 if (spec
->multiout
.dig_out_nid
&&
1352 spec
->stream_digital_playback
) {
1353 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_digital_playback
);
1354 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
1356 if (spec
->dig_in_nid
&&
1357 spec
->stream_digital_capture
) {
1358 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_digital_capture
);
1359 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
1366 static void alc_free(struct hda_codec
*codec
)
1368 struct alc_spec
*spec
= codec
->spec
;
1374 if (spec
->kctl_alloc
) {
1375 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
1376 kfree(spec
->kctl_alloc
[i
].name
);
1377 kfree(spec
->kctl_alloc
);
1384 static struct hda_codec_ops alc_patch_ops
= {
1385 .build_controls
= alc_build_controls
,
1386 .build_pcms
= alc_build_pcms
,
1390 .resume
= alc_resume
,
1396 * Test configuration for debugging
1398 * Almost all inputs/outputs are enabled. I/O pins can be configured via
1401 #ifdef CONFIG_SND_DEBUG
1402 static hda_nid_t alc880_test_dac_nids
[4] = {
1403 0x02, 0x03, 0x04, 0x05
1406 static struct hda_input_mux alc880_test_capture_source
= {
1417 static struct hda_channel_mode alc880_test_modes
[4] = {
1424 static int alc_test_pin_ctl_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1426 static char *texts
[] = {
1427 "N/A", "Line Out", "HP Out",
1428 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1430 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1432 uinfo
->value
.enumerated
.items
= 8;
1433 if (uinfo
->value
.enumerated
.item
>= 8)
1434 uinfo
->value
.enumerated
.item
= 7;
1435 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1439 static int alc_test_pin_ctl_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1441 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1442 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1443 unsigned int pin_ctl
, item
= 0;
1445 pin_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1446 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1447 if (pin_ctl
& AC_PINCTL_OUT_EN
) {
1448 if (pin_ctl
& AC_PINCTL_HP_EN
)
1452 } else if (pin_ctl
& AC_PINCTL_IN_EN
) {
1453 switch (pin_ctl
& AC_PINCTL_VREFEN
) {
1454 case AC_PINCTL_VREF_HIZ
: item
= 3; break;
1455 case AC_PINCTL_VREF_50
: item
= 4; break;
1456 case AC_PINCTL_VREF_GRD
: item
= 5; break;
1457 case AC_PINCTL_VREF_80
: item
= 6; break;
1458 case AC_PINCTL_VREF_100
: item
= 7; break;
1461 ucontrol
->value
.enumerated
.item
[0] = item
;
1465 static int alc_test_pin_ctl_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1467 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1468 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1469 static unsigned int ctls
[] = {
1470 0, AC_PINCTL_OUT_EN
, AC_PINCTL_OUT_EN
| AC_PINCTL_HP_EN
,
1471 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_HIZ
,
1472 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_50
,
1473 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_GRD
,
1474 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_80
,
1475 AC_PINCTL_IN_EN
| AC_PINCTL_VREF_100
,
1477 unsigned int old_ctl
, new_ctl
;
1479 old_ctl
= snd_hda_codec_read(codec
, nid
, 0,
1480 AC_VERB_GET_PIN_WIDGET_CONTROL
, 0);
1481 new_ctl
= ctls
[ucontrol
->value
.enumerated
.item
[0]];
1482 if (old_ctl
!= new_ctl
) {
1483 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, new_ctl
);
1484 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
1485 ucontrol
->value
.enumerated
.item
[0] >= 3 ? 0xb080 : 0xb000);
1491 static int alc_test_pin_src_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
1493 static char *texts
[] = {
1494 "Front", "Surround", "CLFE", "Side"
1496 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
1498 uinfo
->value
.enumerated
.items
= 4;
1499 if (uinfo
->value
.enumerated
.item
>= 4)
1500 uinfo
->value
.enumerated
.item
= 3;
1501 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
1505 static int alc_test_pin_src_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1507 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1508 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1511 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0);
1512 ucontrol
->value
.enumerated
.item
[0] = sel
& 3;
1516 static int alc_test_pin_src_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
1518 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1519 hda_nid_t nid
= (hda_nid_t
)kcontrol
->private_value
;
1522 sel
= snd_hda_codec_read(codec
, nid
, 0, AC_VERB_GET_CONNECT_SEL
, 0) & 3;
1523 if (ucontrol
->value
.enumerated
.item
[0] != sel
) {
1524 sel
= ucontrol
->value
.enumerated
.item
[0] & 3;
1525 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_CONNECT_SEL
, sel
);
1531 #define PIN_CTL_TEST(xname,nid) { \
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1534 .info = alc_test_pin_ctl_info, \
1535 .get = alc_test_pin_ctl_get, \
1536 .put = alc_test_pin_ctl_put, \
1537 .private_value = nid \
1540 #define PIN_SRC_TEST(xname,nid) { \
1541 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1543 .info = alc_test_pin_src_info, \
1544 .get = alc_test_pin_src_get, \
1545 .put = alc_test_pin_src_put, \
1546 .private_value = nid \
1549 static struct snd_kcontrol_new alc880_test_mixer
[] = {
1550 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
1551 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
1552 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT
),
1553 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
1554 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
1555 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
1556 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT
),
1557 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
1558 PIN_CTL_TEST("Front Pin Mode", 0x14),
1559 PIN_CTL_TEST("Surround Pin Mode", 0x15),
1560 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1561 PIN_CTL_TEST("Side Pin Mode", 0x17),
1562 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1563 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1564 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1565 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1566 PIN_SRC_TEST("In-1 Pin Source", 0x18),
1567 PIN_SRC_TEST("In-2 Pin Source", 0x19),
1568 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1569 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1570 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT
),
1571 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT
),
1572 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT
),
1573 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT
),
1574 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT
),
1575 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT
),
1576 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT
),
1577 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT
),
1578 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT
),
1579 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT
),
1581 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1582 .name
= "Channel Mode",
1583 .info
= alc_ch_mode_info
,
1584 .get
= alc_ch_mode_get
,
1585 .put
= alc_ch_mode_put
,
1590 static struct hda_verb alc880_test_init_verbs
[] = {
1591 /* Unmute inputs of 0x0c - 0x0f */
1592 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1593 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1594 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1595 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1596 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1597 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1598 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1599 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1600 /* Vol output for 0x0c-0x0f */
1601 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1602 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1603 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1604 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1605 /* Set output pins 0x14-0x17 */
1606 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1607 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1608 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1609 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
1610 /* Unmute output pins 0x14-0x17 */
1611 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1612 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1613 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1614 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
1615 /* Set input pins 0x18-0x1c */
1616 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1617 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
1618 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1619 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1620 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
1621 /* Mute input pins 0x18-0x1b */
1622 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1623 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1624 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1625 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
1627 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1628 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
1629 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1630 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
1631 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1632 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
1633 /* Analog input/passthru */
1634 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
1635 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
1636 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
1637 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
1638 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
1646 static struct hda_board_config alc880_cfg_tbl
[] = {
1647 /* Back 3 jack, front 2 jack */
1648 { .modelname
= "3stack", .config
= ALC880_3ST
},
1649 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe200, .config
= ALC880_3ST
},
1650 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe201, .config
= ALC880_3ST
},
1651 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe202, .config
= ALC880_3ST
},
1652 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe203, .config
= ALC880_3ST
},
1653 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe204, .config
= ALC880_3ST
},
1654 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe205, .config
= ALC880_3ST
},
1655 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe206, .config
= ALC880_3ST
},
1656 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe207, .config
= ALC880_3ST
},
1657 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe208, .config
= ALC880_3ST
},
1658 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe209, .config
= ALC880_3ST
},
1659 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20a, .config
= ALC880_3ST
},
1660 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20b, .config
= ALC880_3ST
},
1661 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20c, .config
= ALC880_3ST
},
1662 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20d, .config
= ALC880_3ST
},
1663 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20e, .config
= ALC880_3ST
},
1664 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe20f, .config
= ALC880_3ST
},
1665 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe210, .config
= ALC880_3ST
},
1666 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe211, .config
= ALC880_3ST
},
1667 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe214, .config
= ALC880_3ST
},
1668 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe302, .config
= ALC880_3ST
},
1669 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe303, .config
= ALC880_3ST
},
1670 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe304, .config
= ALC880_3ST
},
1671 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe306, .config
= ALC880_3ST
},
1672 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe307, .config
= ALC880_3ST
},
1673 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe404, .config
= ALC880_3ST
},
1674 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa101, .config
= ALC880_3ST
},
1675 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3031, .config
= ALC880_3ST
},
1676 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4036, .config
= ALC880_3ST
},
1677 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4037, .config
= ALC880_3ST
},
1678 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4038, .config
= ALC880_3ST
},
1679 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4040, .config
= ALC880_3ST
},
1680 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4041, .config
= ALC880_3ST
},
1682 { .pci_subvendor
= 0x19db, .pci_subdevice
= 0x4188, .config
= ALC880_TCL_S700
},
1684 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1685 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe310, .config
= ALC880_3ST
},
1686 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81d6, .config
= ALC880_3ST
},
1687 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81a0, .config
= ALC880_3ST
},
1689 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1690 { .modelname
= "3stack-digout", .config
= ALC880_3ST_DIG
},
1691 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe308, .config
= ALC880_3ST_DIG
},
1692 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0070, .config
= ALC880_3ST_DIG
},
1693 /* Clevo m520G NB */
1694 { .pci_subvendor
= 0x1558, .pci_subdevice
= 0x0520, .config
= ALC880_CLEVO
},
1696 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1697 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe305, .config
= ALC880_3ST_DIG
},
1698 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd402, .config
= ALC880_3ST_DIG
},
1699 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0xe309, .config
= ALC880_3ST_DIG
},
1701 /* Back 5 jack, front 2 jack */
1702 { .modelname
= "5stack", .config
= ALC880_5ST
},
1703 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3033, .config
= ALC880_5ST
},
1704 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x4039, .config
= ALC880_5ST
},
1705 { .pci_subvendor
= 0x107b, .pci_subdevice
= 0x3032, .config
= ALC880_5ST
},
1706 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x2a09, .config
= ALC880_5ST
},
1707 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x814e, .config
= ALC880_5ST
},
1709 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1710 { .modelname
= "5stack-digout", .config
= ALC880_5ST_DIG
},
1711 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe224, .config
= ALC880_5ST_DIG
},
1712 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe400, .config
= ALC880_5ST_DIG
},
1713 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe401, .config
= ALC880_5ST_DIG
},
1714 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xe402, .config
= ALC880_5ST_DIG
},
1715 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd400, .config
= ALC880_5ST_DIG
},
1716 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd401, .config
= ALC880_5ST_DIG
},
1717 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xa100, .config
= ALC880_5ST_DIG
},
1718 { .pci_subvendor
= 0x1565, .pci_subdevice
= 0x8202, .config
= ALC880_5ST_DIG
},
1719 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa880, .config
= ALC880_5ST_DIG
},
1720 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1721 { .pci_subvendor
= 0x1695, .pci_subdevice
= 0x400d, .config
= ALC880_5ST_DIG
},
1722 /* note subvendor = 0 below */
1723 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1725 { .modelname
= "w810", .config
= ALC880_W810
},
1726 { .pci_subvendor
= 0x161f, .pci_subdevice
= 0x203d, .config
= ALC880_W810
},
1728 { .modelname
= "z71v", .config
= ALC880_Z71V
},
1729 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_Z71V
},
1731 { .modelname
= "6stack", .config
= ALC880_6ST
},
1732 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x8196, .config
= ALC880_6ST
}, /* ASUS P5GD1-HVM */
1733 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x81b4, .config
= ALC880_6ST
},
1734 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0xa884, .config
= ALC880_6ST
}, /* Acer APFV */
1735 { .pci_subvendor
= 0x1458, .pci_subdevice
= 0xa102, .config
= ALC880_6ST
}, /* Gigabyte K8N51 */
1737 { .modelname
= "6stack-digout", .config
= ALC880_6ST_DIG
},
1738 { .pci_subvendor
= 0x2668, .pci_subdevice
= 0x8086, .config
= ALC880_6ST_DIG
},
1739 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0x2668, .config
= ALC880_6ST_DIG
},
1740 { .pci_subvendor
= 0x1462, .pci_subdevice
= 0x1150, .config
= ALC880_6ST_DIG
},
1741 { .pci_subvendor
= 0xe803, .pci_subdevice
= 0x1019, .config
= ALC880_6ST_DIG
},
1742 { .pci_subvendor
= 0x1039, .pci_subdevice
= 0x1234, .config
= ALC880_6ST_DIG
},
1743 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0077, .config
= ALC880_6ST_DIG
},
1744 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0078, .config
= ALC880_6ST_DIG
},
1745 { .pci_subvendor
= 0x1025, .pci_subdevice
= 0x0087, .config
= ALC880_6ST_DIG
},
1746 { .pci_subvendor
= 0x1297, .pci_subdevice
= 0xc790, .config
= ALC880_6ST_DIG
}, /* Shuttle ST20G5 */
1748 { .modelname
= "asus", .config
= ALC880_ASUS
},
1749 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1964, .config
= ALC880_ASUS_DIG
},
1750 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1973, .config
= ALC880_ASUS_DIG
},
1751 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x19b3, .config
= ALC880_ASUS_DIG
},
1752 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1113, .config
= ALC880_ASUS_DIG
},
1753 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1173, .config
= ALC880_ASUS_DIG
},
1754 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1993, .config
= ALC880_ASUS
},
1755 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10c3, .config
= ALC880_ASUS_DIG
},
1756 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1133, .config
= ALC880_ASUS
},
1757 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1123, .config
= ALC880_ASUS_DIG
},
1758 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x1143, .config
= ALC880_ASUS
},
1759 { .pci_subvendor
= 0x1043, .pci_subdevice
= 0x10b3, .config
= ALC880_ASUS_W1V
},
1760 { .pci_subvendor
= 0x1558, .pci_subdevice
= 0x5401, .config
= ALC880_ASUS_DIG2
},
1762 { .modelname
= "uniwill", .config
= ALC880_UNIWILL_DIG
},
1763 { .pci_subvendor
= 0x1584, .pci_subdevice
= 0x9050, .config
= ALC880_UNIWILL_DIG
},
1765 { .modelname
= "F1734", .config
= ALC880_F1734
},
1766 { .pci_subvendor
= 0x1734, .pci_subdevice
= 0x107c, .config
= ALC880_F1734
},
1767 { .pci_subvendor
= 0x1584, .pci_subdevice
= 0x9054, .config
= ALC880_F1734
},
1769 #ifdef CONFIG_SND_DEBUG
1770 { .modelname
= "test", .config
= ALC880_TEST
},
1772 { .modelname
= "auto", .config
= ALC880_AUTO
},
1778 * ALC880 codec presets
1780 static struct alc_config_preset alc880_presets
[] = {
1782 .mixers
= { alc880_three_stack_mixer
},
1783 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_3stack_init_verbs
},
1784 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1785 .dac_nids
= alc880_dac_nids
,
1786 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1787 .channel_mode
= alc880_threestack_modes
,
1788 .input_mux
= &alc880_capture_source
,
1790 [ALC880_3ST_DIG
] = {
1791 .mixers
= { alc880_three_stack_mixer
},
1792 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_3stack_init_verbs
},
1793 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1794 .dac_nids
= alc880_dac_nids
,
1795 .dig_out_nid
= ALC880_DIGOUT_NID
,
1796 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1797 .channel_mode
= alc880_threestack_modes
,
1798 .input_mux
= &alc880_capture_source
,
1800 [ALC880_TCL_S700
] = {
1801 .mixers
= { alc880_tcl_s700_mixer
},
1802 .init_verbs
= { alc880_volume_init_verbs
,
1803 alc880_pin_tcl_S700_init_verbs
,
1804 alc880_gpio2_init_verbs
},
1805 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1806 .dac_nids
= alc880_dac_nids
,
1808 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
1809 .channel_mode
= alc880_2_jack_modes
,
1810 .input_mux
= &alc880_capture_source
,
1813 .mixers
= { alc880_three_stack_mixer
, alc880_five_stack_mixer
},
1814 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_5stack_init_verbs
},
1815 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1816 .dac_nids
= alc880_dac_nids
,
1817 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1818 .channel_mode
= alc880_fivestack_modes
,
1819 .input_mux
= &alc880_capture_source
,
1821 [ALC880_5ST_DIG
] = {
1822 .mixers
= { alc880_three_stack_mixer
, alc880_five_stack_mixer
},
1823 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_5stack_init_verbs
},
1824 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1825 .dac_nids
= alc880_dac_nids
,
1826 .dig_out_nid
= ALC880_DIGOUT_NID
,
1827 .num_channel_mode
= ARRAY_SIZE(alc880_fivestack_modes
),
1828 .channel_mode
= alc880_fivestack_modes
,
1829 .input_mux
= &alc880_capture_source
,
1832 .mixers
= { alc880_six_stack_mixer
},
1833 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_6stack_init_verbs
},
1834 .num_dacs
= ARRAY_SIZE(alc880_6st_dac_nids
),
1835 .dac_nids
= alc880_6st_dac_nids
,
1836 .num_channel_mode
= ARRAY_SIZE(alc880_sixstack_modes
),
1837 .channel_mode
= alc880_sixstack_modes
,
1838 .input_mux
= &alc880_6stack_capture_source
,
1840 [ALC880_6ST_DIG
] = {
1841 .mixers
= { alc880_six_stack_mixer
},
1842 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_6stack_init_verbs
},
1843 .num_dacs
= ARRAY_SIZE(alc880_6st_dac_nids
),
1844 .dac_nids
= alc880_6st_dac_nids
,
1845 .dig_out_nid
= ALC880_DIGOUT_NID
,
1846 .num_channel_mode
= ARRAY_SIZE(alc880_sixstack_modes
),
1847 .channel_mode
= alc880_sixstack_modes
,
1848 .input_mux
= &alc880_6stack_capture_source
,
1851 .mixers
= { alc880_w810_base_mixer
},
1852 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_w810_init_verbs
,
1853 alc880_gpio2_init_verbs
},
1854 .num_dacs
= ARRAY_SIZE(alc880_w810_dac_nids
),
1855 .dac_nids
= alc880_w810_dac_nids
,
1856 .dig_out_nid
= ALC880_DIGOUT_NID
,
1857 .num_channel_mode
= ARRAY_SIZE(alc880_w810_modes
),
1858 .channel_mode
= alc880_w810_modes
,
1859 .input_mux
= &alc880_capture_source
,
1862 .mixers
= { alc880_z71v_mixer
},
1863 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_z71v_init_verbs
},
1864 .num_dacs
= ARRAY_SIZE(alc880_z71v_dac_nids
),
1865 .dac_nids
= alc880_z71v_dac_nids
,
1866 .dig_out_nid
= ALC880_DIGOUT_NID
,
1868 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
1869 .channel_mode
= alc880_2_jack_modes
,
1870 .input_mux
= &alc880_capture_source
,
1873 .mixers
= { alc880_f1734_mixer
},
1874 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_f1734_init_verbs
},
1875 .num_dacs
= ARRAY_SIZE(alc880_f1734_dac_nids
),
1876 .dac_nids
= alc880_f1734_dac_nids
,
1878 .num_channel_mode
= ARRAY_SIZE(alc880_2_jack_modes
),
1879 .channel_mode
= alc880_2_jack_modes
,
1880 .input_mux
= &alc880_capture_source
,
1883 .mixers
= { alc880_asus_mixer
},
1884 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
1885 alc880_gpio1_init_verbs
},
1886 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
1887 .dac_nids
= alc880_asus_dac_nids
,
1888 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
1889 .channel_mode
= alc880_asus_modes
,
1890 .input_mux
= &alc880_capture_source
,
1892 [ALC880_ASUS_DIG
] = {
1893 .mixers
= { alc880_asus_mixer
},
1894 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
1895 alc880_gpio1_init_verbs
},
1896 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
1897 .dac_nids
= alc880_asus_dac_nids
,
1898 .dig_out_nid
= ALC880_DIGOUT_NID
,
1899 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
1900 .channel_mode
= alc880_asus_modes
,
1901 .input_mux
= &alc880_capture_source
,
1903 [ALC880_ASUS_DIG2
] = {
1904 .mixers
= { alc880_asus_mixer
},
1905 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
1906 alc880_gpio2_init_verbs
}, /* use GPIO2 */
1907 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
1908 .dac_nids
= alc880_asus_dac_nids
,
1909 .dig_out_nid
= ALC880_DIGOUT_NID
,
1910 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
1911 .channel_mode
= alc880_asus_modes
,
1912 .input_mux
= &alc880_capture_source
,
1914 [ALC880_ASUS_W1V
] = {
1915 .mixers
= { alc880_asus_mixer
, alc880_asus_w1v_mixer
},
1916 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
,
1917 alc880_gpio1_init_verbs
},
1918 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
1919 .dac_nids
= alc880_asus_dac_nids
,
1920 .dig_out_nid
= ALC880_DIGOUT_NID
,
1921 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
1922 .channel_mode
= alc880_asus_modes
,
1923 .input_mux
= &alc880_capture_source
,
1925 [ALC880_UNIWILL_DIG
] = {
1926 .mixers
= { alc880_asus_mixer
, alc880_pcbeep_mixer
},
1927 .init_verbs
= { alc880_volume_init_verbs
, alc880_pin_asus_init_verbs
},
1928 .num_dacs
= ARRAY_SIZE(alc880_asus_dac_nids
),
1929 .dac_nids
= alc880_asus_dac_nids
,
1930 .dig_out_nid
= ALC880_DIGOUT_NID
,
1931 .num_channel_mode
= ARRAY_SIZE(alc880_asus_modes
),
1932 .channel_mode
= alc880_asus_modes
,
1933 .input_mux
= &alc880_capture_source
,
1936 .mixers
= { alc880_three_stack_mixer
},
1937 .init_verbs
= { alc880_volume_init_verbs
,
1938 alc880_pin_clevo_init_verbs
},
1939 .num_dacs
= ARRAY_SIZE(alc880_dac_nids
),
1940 .dac_nids
= alc880_dac_nids
,
1942 .num_channel_mode
= ARRAY_SIZE(alc880_threestack_modes
),
1943 .channel_mode
= alc880_threestack_modes
,
1944 .input_mux
= &alc880_capture_source
,
1946 #ifdef CONFIG_SND_DEBUG
1948 .mixers
= { alc880_test_mixer
},
1949 .init_verbs
= { alc880_test_init_verbs
},
1950 .num_dacs
= ARRAY_SIZE(alc880_test_dac_nids
),
1951 .dac_nids
= alc880_test_dac_nids
,
1952 .dig_out_nid
= ALC880_DIGOUT_NID
,
1953 .num_channel_mode
= ARRAY_SIZE(alc880_test_modes
),
1954 .channel_mode
= alc880_test_modes
,
1955 .input_mux
= &alc880_test_capture_source
,
1961 * Automatic parse of I/O pins from the BIOS configuration
1964 #define NUM_CONTROL_ALLOC 32
1965 #define NUM_VERB_ALLOC 32
1969 ALC_CTL_WIDGET_MUTE
,
1972 static struct snd_kcontrol_new alc880_control_templates
[] = {
1973 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
1974 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
1975 HDA_BIND_MUTE(NULL
, 0, 0, 0),
1978 /* add dynamic controls */
1979 static int add_control(struct alc_spec
*spec
, int type
, const char *name
, unsigned long val
)
1981 struct snd_kcontrol_new
*knew
;
1983 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
1984 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
1986 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
); /* array + terminator */
1989 if (spec
->kctl_alloc
) {
1990 memcpy(knew
, spec
->kctl_alloc
, sizeof(*knew
) * spec
->num_kctl_alloc
);
1991 kfree(spec
->kctl_alloc
);
1993 spec
->kctl_alloc
= knew
;
1994 spec
->num_kctl_alloc
= num
;
1997 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
1998 *knew
= alc880_control_templates
[type
];
1999 knew
->name
= kstrdup(name
, GFP_KERNEL
);
2002 knew
->private_value
= val
;
2003 spec
->num_kctl_used
++;
2007 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
2008 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
2009 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
2010 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
2011 #define alc880_is_input_pin(nid) ((nid) >= 0x18)
2012 #define alc880_input_pin_idx(nid) ((nid) - 0x18)
2013 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
2014 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
2015 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
2016 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
2017 #define ALC880_PIN_CD_NID 0x1c
2019 /* fill in the dac_nids table from the parsed pin configuration */
2020 static int alc880_auto_fill_dac_nids(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
2026 memset(assigned
, 0, sizeof(assigned
));
2027 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2029 /* check the pins hardwired to audio widget */
2030 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2031 nid
= cfg
->line_out_pins
[i
];
2032 if (alc880_is_fixed_pin(nid
)) {
2033 int idx
= alc880_fixed_pin_idx(nid
);
2034 spec
->multiout
.dac_nids
[i
] = alc880_idx_to_dac(idx
);
2038 /* left pins can be connect to any audio widget */
2039 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2040 nid
= cfg
->line_out_pins
[i
];
2041 if (alc880_is_fixed_pin(nid
))
2043 /* search for an empty channel */
2044 for (j
= 0; j
< cfg
->line_outs
; j
++) {
2045 if (! assigned
[j
]) {
2046 spec
->multiout
.dac_nids
[i
] = alc880_idx_to_dac(j
);
2052 spec
->multiout
.num_dacs
= cfg
->line_outs
;
2056 /* add playback controls from the parsed DAC table */
2057 static int alc880_auto_create_multi_out_ctls(struct alc_spec
*spec
,
2058 const struct auto_pin_cfg
*cfg
)
2061 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
2065 for (i
= 0; i
< cfg
->line_outs
; i
++) {
2066 if (! spec
->multiout
.dac_nids
[i
])
2068 nid
= alc880_idx_to_mixer(alc880_dac_to_idx(spec
->multiout
.dac_nids
[i
]));
2071 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Center Playback Volume",
2072 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
2074 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "LFE Playback Volume",
2075 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
2077 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "Center Playback Switch",
2078 HDA_COMPOSE_AMP_VAL(nid
, 1, 2, HDA_INPUT
))) < 0)
2080 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "LFE Playback Switch",
2081 HDA_COMPOSE_AMP_VAL(nid
, 2, 2, HDA_INPUT
))) < 0)
2084 sprintf(name
, "%s Playback Volume", chname
[i
]);
2085 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2086 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
2088 sprintf(name
, "%s Playback Switch", chname
[i
]);
2089 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
2090 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2097 /* add playback controls for speaker and HP outputs */
2098 static int alc880_auto_create_extra_out(struct alc_spec
*spec
, hda_nid_t pin
,
2108 if (alc880_is_fixed_pin(pin
)) {
2109 nid
= alc880_idx_to_dac(alc880_fixed_pin_idx(pin
));
2110 if (! spec
->multiout
.dac_nids
[0]) {
2111 /* use this as the primary output */
2112 spec
->multiout
.dac_nids
[0] = nid
;
2113 if (! spec
->multiout
.num_dacs
)
2114 spec
->multiout
.num_dacs
= 1;
2116 /* specify the DAC as the extra output */
2117 spec
->multiout
.hp_nid
= nid
;
2118 /* control HP volume/switch on the output mixer amp */
2119 nid
= alc880_idx_to_mixer(alc880_fixed_pin_idx(pin
));
2120 sprintf(name
, "%s Playback Volume", pfx
);
2121 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2122 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
2124 sprintf(name
, "%s Playback Switch", pfx
);
2125 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
2126 HDA_COMPOSE_AMP_VAL(nid
, 3, 2, HDA_INPUT
))) < 0)
2128 } else if (alc880_is_multi_pin(pin
)) {
2129 /* set manual connection */
2130 if (! spec
->multiout
.dac_nids
[0]) {
2131 /* use this as the primary output */
2132 spec
->multiout
.dac_nids
[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin
));
2133 if (! spec
->multiout
.num_dacs
)
2134 spec
->multiout
.num_dacs
= 1;
2136 /* we have only a switch on HP-out PIN */
2137 sprintf(name
, "%s Playback Switch", pfx
);
2138 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
,
2139 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
))) < 0)
2145 /* create input playback/capture controls for the given pin */
2146 static int new_analog_input(struct alc_spec
*spec
, hda_nid_t pin
, const char *ctlname
,
2147 int idx
, hda_nid_t mix_nid
)
2152 sprintf(name
, "%s Playback Volume", ctlname
);
2153 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
,
2154 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
))) < 0)
2156 sprintf(name
, "%s Playback Switch", ctlname
);
2157 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
,
2158 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
))) < 0)
2163 /* create playback/capture controls for input pins */
2164 static int alc880_auto_create_analog_input_ctls(struct alc_spec
*spec
,
2165 const struct auto_pin_cfg
*cfg
)
2167 struct hda_input_mux
*imux
= &spec
->private_imux
;
2170 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2171 if (alc880_is_input_pin(cfg
->input_pins
[i
])) {
2172 idx
= alc880_input_pin_idx(cfg
->input_pins
[i
]);
2173 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
2174 auto_pin_cfg_labels
[i
],
2178 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
2179 imux
->items
[imux
->num_items
].index
= alc880_input_pin_idx(cfg
->input_pins
[i
]);
2186 static void alc880_auto_set_output_and_unmute(struct hda_codec
*codec
,
2187 hda_nid_t nid
, int pin_type
,
2191 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
2192 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
2193 /* need the manual connection? */
2194 if (alc880_is_multi_pin(nid
)) {
2195 struct alc_spec
*spec
= codec
->spec
;
2196 int idx
= alc880_multi_pin_idx(nid
);
2197 snd_hda_codec_write(codec
, alc880_idx_to_selector(idx
), 0,
2198 AC_VERB_SET_CONNECT_SEL
,
2199 alc880_dac_to_idx(spec
->multiout
.dac_nids
[dac_idx
]));
2203 static void alc880_auto_init_multi_out(struct hda_codec
*codec
)
2205 struct alc_spec
*spec
= codec
->spec
;
2208 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
2209 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
2210 alc880_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
2214 static void alc880_auto_init_extra_out(struct hda_codec
*codec
)
2216 struct alc_spec
*spec
= codec
->spec
;
2219 pin
= spec
->autocfg
.speaker_pin
;
2220 if (pin
) /* connect to front */
2221 alc880_auto_set_output_and_unmute(codec
, pin
, PIN_OUT
, 0);
2222 pin
= spec
->autocfg
.hp_pin
;
2223 if (pin
) /* connect to front */
2224 alc880_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
2227 static void alc880_auto_init_analog_input(struct hda_codec
*codec
)
2229 struct alc_spec
*spec
= codec
->spec
;
2232 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2233 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
2234 if (alc880_is_input_pin(nid
)) {
2235 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
2236 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
2237 if (nid
!= ALC880_PIN_CD_NID
)
2238 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
2244 /* parse the BIOS configuration and set up the alc_spec */
2245 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2246 static int alc880_parse_auto_config(struct hda_codec
*codec
)
2248 struct alc_spec
*spec
= codec
->spec
;
2250 static hda_nid_t alc880_ignore
[] = { 0x1d, 0 };
2252 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
2253 alc880_ignore
)) < 0)
2255 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
2256 ! spec
->autocfg
.hp_pin
)
2257 return 0; /* can't find valid BIOS pin config */
2259 if ((err
= alc880_auto_fill_dac_nids(spec
, &spec
->autocfg
)) < 0 ||
2260 (err
= alc880_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
2261 (err
= alc880_auto_create_extra_out(spec
, spec
->autocfg
.speaker_pin
,
2263 (err
= alc880_auto_create_extra_out(spec
, spec
->autocfg
.speaker_pin
,
2264 "Headphone")) < 0 ||
2265 (err
= alc880_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
2268 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
2270 if (spec
->autocfg
.dig_out_pin
)
2271 spec
->multiout
.dig_out_nid
= ALC880_DIGOUT_NID
;
2272 if (spec
->autocfg
.dig_in_pin
)
2273 spec
->dig_in_nid
= ALC880_DIGIN_NID
;
2275 if (spec
->kctl_alloc
)
2276 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
2278 spec
->init_verbs
[spec
->num_init_verbs
++] = alc880_volume_init_verbs
;
2280 spec
->input_mux
= &spec
->private_imux
;
2285 /* init callback for auto-configuration model -- overriding the default init */
2286 static int alc880_auto_init(struct hda_codec
*codec
)
2289 alc880_auto_init_multi_out(codec
);
2290 alc880_auto_init_extra_out(codec
);
2291 alc880_auto_init_analog_input(codec
);
2296 * OK, here we have finally the patch for ALC880
2299 static int patch_alc880(struct hda_codec
*codec
)
2301 struct alc_spec
*spec
;
2305 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
2311 board_config
= snd_hda_check_board_config(codec
, alc880_cfg_tbl
);
2312 if (board_config
< 0 || board_config
>= ALC880_MODEL_LAST
) {
2313 printk(KERN_INFO
"hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2314 board_config
= ALC880_AUTO
;
2317 if (board_config
== ALC880_AUTO
) {
2318 /* automatic parse from the BIOS config */
2319 err
= alc880_parse_auto_config(codec
);
2324 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
2325 board_config
= ALC880_3ST
;
2329 if (board_config
!= ALC880_AUTO
)
2330 setup_preset(spec
, &alc880_presets
[board_config
]);
2332 spec
->stream_name_analog
= "ALC880 Analog";
2333 spec
->stream_analog_playback
= &alc880_pcm_analog_playback
;
2334 spec
->stream_analog_capture
= &alc880_pcm_analog_capture
;
2336 spec
->stream_name_digital
= "ALC880 Digital";
2337 spec
->stream_digital_playback
= &alc880_pcm_digital_playback
;
2338 spec
->stream_digital_capture
= &alc880_pcm_digital_capture
;
2340 if (! spec
->adc_nids
&& spec
->input_mux
) {
2341 /* check whether NID 0x07 is valid */
2342 unsigned int wcap
= get_wcaps(codec
, alc880_adc_nids
[0]);
2343 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
2344 if (wcap
!= AC_WID_AUD_IN
) {
2345 spec
->adc_nids
= alc880_adc_nids_alt
;
2346 spec
->num_adc_nids
= ARRAY_SIZE(alc880_adc_nids_alt
);
2347 spec
->mixers
[spec
->num_mixers
] = alc880_capture_alt_mixer
;
2350 spec
->adc_nids
= alc880_adc_nids
;
2351 spec
->num_adc_nids
= ARRAY_SIZE(alc880_adc_nids
);
2352 spec
->mixers
[spec
->num_mixers
] = alc880_capture_mixer
;
2357 codec
->patch_ops
= alc_patch_ops
;
2358 if (board_config
== ALC880_AUTO
)
2359 codec
->patch_ops
.init
= alc880_auto_init
;
2369 static hda_nid_t alc260_dac_nids
[1] = {
2374 static hda_nid_t alc260_adc_nids
[1] = {
2379 static hda_nid_t alc260_adc_nids_alt
[1] = {
2384 static hda_nid_t alc260_hp_adc_nids
[2] = {
2389 static hda_nid_t alc260_fujitsu_adc_nids
[2] = {
2394 #define ALC260_DIGOUT_NID 0x03
2395 #define ALC260_DIGIN_NID 0x06
2397 static struct hda_input_mux alc260_capture_source
= {
2401 { "Front Mic", 0x1 },
2407 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
2408 * and the internal CD lines.
2410 static struct hda_input_mux alc260_fujitsu_capture_source
= {
2413 { "Mic/Line", 0x0 },
2415 { "Headphone", 0x2 },
2420 * This is just place-holder, so there's something for alc_build_pcms to look
2421 * at when it calculates the maximum number of channels. ALC260 has no mixer
2422 * element which allows changing the channel mode, so the verb list is
2425 static struct hda_channel_mode alc260_modes
[1] = {
2430 /* Mixer combinations
2432 * basic: base_output + input + pc_beep + capture
2433 * HP: base_output + input + capture_alt
2434 * HP_3013: hp_3013 + input + capture
2435 * fujitsu: fujitsu + capture
2438 static struct snd_kcontrol_new alc260_base_output_mixer
[] = {
2439 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2440 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT
),
2441 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2442 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT
),
2443 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2444 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT
),
2448 static struct snd_kcontrol_new alc260_input_mixer
[] = {
2449 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2450 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2451 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT
),
2452 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT
),
2453 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT
),
2454 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT
),
2455 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT
),
2456 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT
),
2460 static struct snd_kcontrol_new alc260_pc_beep_mixer
[] = {
2461 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT
),
2462 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT
),
2466 static struct snd_kcontrol_new alc260_hp_3013_mixer
[] = {
2467 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2468 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT
),
2469 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT
),
2470 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT
),
2471 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2472 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
2473 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT
),
2474 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT
),
2478 static struct snd_kcontrol_new alc260_fujitsu_mixer
[] = {
2479 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT
),
2480 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT
),
2481 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT
),
2482 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT
),
2483 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT
),
2484 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT
),
2485 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT
),
2486 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN
),
2487 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT
),
2488 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT
),
2489 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT
),
2490 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT
),
2494 /* capture mixer elements */
2495 static struct snd_kcontrol_new alc260_capture_mixer
[] = {
2496 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT
),
2497 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT
),
2498 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT
),
2499 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT
),
2501 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2502 /* The multiple "Capture Source" controls confuse alsamixer
2503 * So call somewhat different..
2504 * FIXME: the controls appear in the "playback" view!
2506 /* .name = "Capture Source", */
2507 .name
= "Input Source",
2509 .info
= alc_mux_enum_info
,
2510 .get
= alc_mux_enum_get
,
2511 .put
= alc_mux_enum_put
,
2516 static struct snd_kcontrol_new alc260_capture_alt_mixer
[] = {
2517 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT
),
2518 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT
),
2520 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2521 /* The multiple "Capture Source" controls confuse alsamixer
2522 * So call somewhat different..
2523 * FIXME: the controls appear in the "playback" view!
2525 /* .name = "Capture Source", */
2526 .name
= "Input Source",
2528 .info
= alc_mux_enum_info
,
2529 .get
= alc_mux_enum_get
,
2530 .put
= alc_mux_enum_put
,
2536 * initialization verbs
2538 static struct hda_verb alc260_init_verbs
[] = {
2539 /* Line In pin widget for input */
2540 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2541 /* CD pin widget for input */
2542 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2543 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2544 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2545 /* Mic2 (front panel) pin widget for input and vref at 80% */
2546 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
2547 /* LINE-2 is used for line-out in rear */
2548 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2549 /* select line-out */
2550 {0x0e, AC_VERB_SET_CONNECT_SEL
, 0x00},
2552 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2554 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2556 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2557 /* mute capture amp left and right */
2558 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2559 /* set connection select to line in (default select for this ADC) */
2560 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2561 /* mute capture amp left and right */
2562 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2563 /* set connection select to line in (default select for this ADC) */
2564 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x02},
2565 /* set vol=0 Line-Out mixer amp left and right */
2566 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2567 /* unmute pin widget amp left and right (no gain on this amp) */
2568 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2569 /* set vol=0 HP mixer amp left and right */
2570 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2571 /* unmute pin widget amp left and right (no gain on this amp) */
2572 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2573 /* set vol=0 Mono mixer amp left and right */
2574 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2575 /* unmute pin widget amp left and right (no gain on this amp) */
2576 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2577 /* unmute LINE-2 out pin */
2578 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2579 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2581 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
2583 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
2585 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2586 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2587 /* mute Front out path */
2588 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2589 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2590 /* mute Headphone out path */
2591 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2592 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2593 /* mute Mono out path */
2594 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2595 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
2599 static struct hda_verb alc260_hp_init_verbs
[] = {
2600 /* Headphone and output */
2601 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
2603 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2604 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2605 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2606 /* Mic2 (front panel) pin widget for input and vref at 80% */
2607 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2608 /* Line In pin widget for input */
2609 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2610 /* Line-2 pin widget for output */
2611 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2612 /* CD pin widget for input */
2613 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2614 /* unmute amp left and right */
2615 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7000},
2616 /* set connection select to line in (default select for this ADC) */
2617 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2618 /* unmute Line-Out mixer amp left and right (volume = 0) */
2619 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2620 /* mute pin widget amp left and right (no gain on this amp) */
2621 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2622 /* unmute HP mixer amp left and right (volume = 0) */
2623 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2624 /* mute pin widget amp left and right (no gain on this amp) */
2625 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2626 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2628 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
2629 /* unmute Line In */
2630 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
2632 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2633 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2634 /* Unmute Front out path */
2635 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2636 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2637 /* Unmute Headphone out path */
2638 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2639 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2640 /* Unmute Mono out path */
2641 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2642 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2646 static struct hda_verb alc260_hp_3013_init_verbs
[] = {
2647 /* Line out and output */
2648 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2650 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
2651 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2652 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2653 /* Mic2 (front panel) pin widget for input and vref at 80% */
2654 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
2655 /* Line In pin widget for input */
2656 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2657 /* Headphone pin widget for output */
2658 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
2659 /* CD pin widget for input */
2660 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
2661 /* unmute amp left and right */
2662 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, 0x7000},
2663 /* set connection select to line in (default select for this ADC) */
2664 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x02},
2665 /* unmute Line-Out mixer amp left and right (volume = 0) */
2666 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2667 /* mute pin widget amp left and right (no gain on this amp) */
2668 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2669 /* unmute HP mixer amp left and right (volume = 0) */
2670 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb000},
2671 /* mute pin widget amp left and right (no gain on this amp) */
2672 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
2673 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2675 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x04 << 8))},
2676 /* unmute Line In */
2677 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8))},
2679 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2680 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2681 /* Unmute Front out path */
2682 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2683 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2684 /* Unmute Headphone out path */
2685 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2686 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2687 /* Unmute Mono out path */
2688 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
2689 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8))},
2693 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2696 static struct hda_verb alc260_fujitsu_init_verbs
[] = {
2697 /* Disable all GPIOs */
2698 {0x01, AC_VERB_SET_GPIO_MASK
, 0},
2699 /* Internal speaker is connected to headphone pin */
2700 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
2701 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
2702 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
2703 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2704 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
2705 /* Ensure all other unused pins are disabled and muted.
2706 * Note: trying to set widget 0x15 to anything blocks all audio
2707 * output for some reason, so just leave that at the default.
2709 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2710 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2711 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2712 {0x11, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2713 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0},
2714 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2715 /* Disable digital (SPDIF) pins */
2716 {0x03, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2717 {0x06, AC_VERB_SET_DIGI_CONVERT_1
, 0},
2719 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
2720 * when acting as an output.
2722 {0x0d, AC_VERB_SET_CONNECT_SEL
, 0},
2724 /* Start with mixer outputs muted */
2725 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2726 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2727 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
2729 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2730 {0x10, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2731 /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
2732 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
2733 /* Unmute Line1 pin widget input for when this pin is used as input
2734 * (no equiv mixer ctrl). Having input and output unmuted doesn't
2735 * seem to cause a problem.
2737 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2738 /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
2739 {0x12, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2741 /* Mute capture amp left and right */
2742 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2743 /* Set ADC connection select to match default mixer setting - line
2746 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
2748 /* Do the same for the second ADC: mute capture input amp and
2749 * set ADC connection to line in
2751 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
2752 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x00},
2754 /* Mute all inputs to mixer widget (even unconnected ones) */
2755 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)}, /* mic1 pin */
2756 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)}, /* mic2 pin */
2757 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)}, /* line1 pin */
2758 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)}, /* line2 pin */
2759 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)}, /* CD pin */
2760 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2761 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(6)}, /* Line-out pin */
2762 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(7)}, /* HP-pin pin */
2767 static struct hda_pcm_stream alc260_pcm_analog_playback
= {
2773 static struct hda_pcm_stream alc260_pcm_analog_capture
= {
2779 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
2780 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
2783 * for BIOS auto-configuration
2786 static int alc260_add_playback_controls(struct alc_spec
*spec
, hda_nid_t nid
,
2790 unsigned long vol_val
, sw_val
;
2794 if (nid
>= 0x0f && nid
< 0x11) {
2795 nid_vol
= nid
- 0x7;
2796 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
);
2797 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
);
2798 } else if (nid
== 0x11) {
2799 nid_vol
= nid
- 0x7;
2800 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
);
2801 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
);
2802 } else if (nid
>= 0x12 && nid
<= 0x15) {
2804 vol_val
= HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
);
2805 sw_val
= HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
);
2809 snprintf(name
, sizeof(name
), "%s Playback Volume", pfx
);
2810 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, name
, vol_val
)) < 0)
2812 snprintf(name
, sizeof(name
), "%s Playback Switch", pfx
);
2813 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, name
, sw_val
)) < 0)
2818 /* add playback controls from the parsed DAC table */
2819 static int alc260_auto_create_multi_out_ctls(struct alc_spec
*spec
,
2820 const struct auto_pin_cfg
*cfg
)
2825 spec
->multiout
.num_dacs
= 1;
2826 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
2827 spec
->multiout
.dac_nids
[0] = 0x02;
2829 nid
= cfg
->line_out_pins
[0];
2831 err
= alc260_add_playback_controls(spec
, nid
, "Front");
2836 nid
= cfg
->speaker_pin
;
2838 err
= alc260_add_playback_controls(spec
, nid
, "Speaker");
2845 err
= alc260_add_playback_controls(spec
, nid
, "Headphone");
2852 /* create playback/capture controls for input pins */
2853 static int alc260_auto_create_analog_input_ctls(struct alc_spec
*spec
,
2854 const struct auto_pin_cfg
*cfg
)
2856 struct hda_input_mux
*imux
= &spec
->private_imux
;
2859 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2860 if (cfg
->input_pins
[i
] >= 0x12) {
2861 idx
= cfg
->input_pins
[i
] - 0x12;
2862 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
2863 auto_pin_cfg_labels
[i
], idx
, 0x07);
2866 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
2867 imux
->items
[imux
->num_items
].index
= idx
;
2870 if ((cfg
->input_pins
[i
] >= 0x0f) && (cfg
->input_pins
[i
] <= 0x10)){
2871 idx
= cfg
->input_pins
[i
] - 0x09;
2872 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
2873 auto_pin_cfg_labels
[i
], idx
, 0x07);
2876 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
2877 imux
->items
[imux
->num_items
].index
= idx
;
2884 static void alc260_auto_set_output_and_unmute(struct hda_codec
*codec
,
2885 hda_nid_t nid
, int pin_type
,
2889 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
2890 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
2891 /* need the manual connection? */
2893 int idx
= nid
- 0x12;
2894 snd_hda_codec_write(codec
, idx
+ 0x0b, 0,
2895 AC_VERB_SET_CONNECT_SEL
, sel_idx
);
2900 static void alc260_auto_init_multi_out(struct hda_codec
*codec
)
2902 struct alc_spec
*spec
= codec
->spec
;
2905 nid
= spec
->autocfg
.line_out_pins
[0];
2907 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
2909 nid
= spec
->autocfg
.speaker_pin
;
2911 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
2913 nid
= spec
->autocfg
.hp_pin
;
2915 alc260_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, 0);
2918 #define ALC260_PIN_CD_NID 0x16
2919 static void alc260_auto_init_analog_input(struct hda_codec
*codec
)
2921 struct alc_spec
*spec
= codec
->spec
;
2924 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
2925 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
2927 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
2928 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
2929 if (nid
!= ALC260_PIN_CD_NID
)
2930 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
2937 * generic initialization of ADC, input mixers and output mixers
2939 static struct hda_verb alc260_volume_init_verbs
[] = {
2941 * Unmute ADC0-1 and set the default input to mic-in
2943 {0x04, AC_VERB_SET_CONNECT_SEL
, 0x00},
2944 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2945 {0x05, AC_VERB_SET_CONNECT_SEL
, 0x00},
2946 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2948 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2950 * Note: PASD motherboards uses the Line In 2 as the input for front panel
2953 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
2954 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2955 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
2956 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
2957 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
2958 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
2961 * Set up output mixers (0x08 - 0x0a)
2963 /* set vol=0 to output mixers */
2964 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2965 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2966 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
2967 /* set up input amps for analog loopback */
2968 /* Amp Indices: DAC = 0, mixer = 1 */
2969 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2970 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
2971 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2972 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
2973 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
2974 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
2979 static int alc260_parse_auto_config(struct hda_codec
*codec
)
2981 struct alc_spec
*spec
= codec
->spec
;
2984 static hda_nid_t alc260_ignore
[] = { 0x17, 0 };
2986 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
2987 alc260_ignore
)) < 0)
2989 if ((err
= alc260_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0)
2991 if (! spec
->kctl_alloc
)
2992 return 0; /* can't find valid BIOS pin config */
2993 if ((err
= alc260_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
2996 spec
->multiout
.max_channels
= 2;
2998 if (spec
->autocfg
.dig_out_pin
)
2999 spec
->multiout
.dig_out_nid
= ALC260_DIGOUT_NID
;
3000 if (spec
->kctl_alloc
)
3001 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
3003 spec
->init_verbs
[spec
->num_init_verbs
++] = alc260_volume_init_verbs
;
3005 spec
->input_mux
= &spec
->private_imux
;
3007 /* check whether NID 0x04 is valid */
3008 wcap
= get_wcaps(codec
, 0x04);
3009 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
3010 if (wcap
!= AC_WID_AUD_IN
) {
3011 spec
->adc_nids
= alc260_adc_nids_alt
;
3012 spec
->num_adc_nids
= ARRAY_SIZE(alc260_adc_nids_alt
);
3013 spec
->mixers
[spec
->num_mixers
] = alc260_capture_alt_mixer
;
3015 spec
->adc_nids
= alc260_adc_nids
;
3016 spec
->num_adc_nids
= ARRAY_SIZE(alc260_adc_nids
);
3017 spec
->mixers
[spec
->num_mixers
] = alc260_capture_mixer
;
3024 /* init callback for auto-configuration model -- overriding the default init */
3025 static int alc260_auto_init(struct hda_codec
*codec
)
3028 alc260_auto_init_multi_out(codec
);
3029 alc260_auto_init_analog_input(codec
);
3034 * ALC260 configurations
3036 static struct hda_board_config alc260_cfg_tbl
[] = {
3037 { .modelname
= "basic", .config
= ALC260_BASIC
},
3038 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81bb,
3039 .config
= ALC260_BASIC
}, /* Sony VAIO */
3040 { .modelname
= "hp", .config
= ALC260_HP
},
3041 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3010, .config
= ALC260_HP
},
3042 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3011, .config
= ALC260_HP
},
3043 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3012, .config
= ALC260_HP
},
3044 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3013, .config
= ALC260_HP_3013
},
3045 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3014, .config
= ALC260_HP
},
3046 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3015, .config
= ALC260_HP
},
3047 { .pci_subvendor
= 0x103c, .pci_subdevice
= 0x3016, .config
= ALC260_HP
},
3048 { .modelname
= "fujitsu", .config
= ALC260_FUJITSU_S702X
},
3049 { .pci_subvendor
= 0x10cf, .pci_subdevice
= 0x1326, .config
= ALC260_FUJITSU_S702X
},
3050 { .modelname
= "auto", .config
= ALC260_AUTO
},
3054 static struct alc_config_preset alc260_presets
[] = {
3056 .mixers
= { alc260_base_output_mixer
,
3058 alc260_pc_beep_mixer
,
3059 alc260_capture_mixer
},
3060 .init_verbs
= { alc260_init_verbs
},
3061 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3062 .dac_nids
= alc260_dac_nids
,
3063 .num_adc_nids
= ARRAY_SIZE(alc260_adc_nids
),
3064 .adc_nids
= alc260_adc_nids
,
3065 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3066 .channel_mode
= alc260_modes
,
3067 .input_mux
= &alc260_capture_source
,
3070 .mixers
= { alc260_base_output_mixer
,
3072 alc260_capture_alt_mixer
},
3073 .init_verbs
= { alc260_hp_init_verbs
},
3074 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3075 .dac_nids
= alc260_dac_nids
,
3076 .num_adc_nids
= ARRAY_SIZE(alc260_hp_adc_nids
),
3077 .adc_nids
= alc260_hp_adc_nids
,
3078 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3079 .channel_mode
= alc260_modes
,
3080 .input_mux
= &alc260_capture_source
,
3082 [ALC260_HP_3013
] = {
3083 .mixers
= { alc260_hp_3013_mixer
,
3085 alc260_capture_alt_mixer
},
3086 .init_verbs
= { alc260_hp_3013_init_verbs
},
3087 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3088 .dac_nids
= alc260_dac_nids
,
3089 .num_adc_nids
= ARRAY_SIZE(alc260_hp_adc_nids
),
3090 .adc_nids
= alc260_hp_adc_nids
,
3091 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3092 .channel_mode
= alc260_modes
,
3093 .input_mux
= &alc260_capture_source
,
3095 [ALC260_FUJITSU_S702X
] = {
3096 .mixers
= { alc260_fujitsu_mixer
,
3097 alc260_capture_mixer
},
3098 .init_verbs
= { alc260_fujitsu_init_verbs
},
3099 .num_dacs
= ARRAY_SIZE(alc260_dac_nids
),
3100 .dac_nids
= alc260_dac_nids
,
3101 .num_adc_nids
= ARRAY_SIZE(alc260_fujitsu_adc_nids
),
3102 .adc_nids
= alc260_fujitsu_adc_nids
,
3103 .num_channel_mode
= ARRAY_SIZE(alc260_modes
),
3104 .channel_mode
= alc260_modes
,
3105 .input_mux
= &alc260_fujitsu_capture_source
,
3109 static int patch_alc260(struct hda_codec
*codec
)
3111 struct alc_spec
*spec
;
3112 int err
, board_config
;
3114 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3120 board_config
= snd_hda_check_board_config(codec
, alc260_cfg_tbl
);
3121 if (board_config
< 0 || board_config
>= ALC260_MODEL_LAST
) {
3122 snd_printd(KERN_INFO
"hda_codec: Unknown model for ALC260\n");
3123 board_config
= ALC260_AUTO
;
3126 if (board_config
== ALC260_AUTO
) {
3127 /* automatic parse from the BIOS config */
3128 err
= alc260_parse_auto_config(codec
);
3133 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3134 board_config
= ALC260_BASIC
;
3138 if (board_config
!= ALC260_AUTO
)
3139 setup_preset(spec
, &alc260_presets
[board_config
]);
3141 spec
->stream_name_analog
= "ALC260 Analog";
3142 spec
->stream_analog_playback
= &alc260_pcm_analog_playback
;
3143 spec
->stream_analog_capture
= &alc260_pcm_analog_capture
;
3145 spec
->stream_name_digital
= "ALC260 Digital";
3146 spec
->stream_digital_playback
= &alc260_pcm_digital_playback
;
3147 spec
->stream_digital_capture
= &alc260_pcm_digital_capture
;
3149 codec
->patch_ops
= alc_patch_ops
;
3150 if (board_config
== ALC260_AUTO
)
3151 codec
->patch_ops
.init
= alc260_auto_init
;
3160 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3161 * configuration. Each pin widget can choose any input DACs and a mixer.
3162 * Each ADC is connected from a mixer of all inputs. This makes possible
3163 * 6-channel independent captures.
3165 * In addition, an independent DAC for the multi-playback (not used in this
3168 #define ALC882_DIGOUT_NID 0x06
3169 #define ALC882_DIGIN_NID 0x0a
3171 static struct hda_channel_mode alc882_ch_modes
[1] = {
3175 static hda_nid_t alc882_dac_nids
[4] = {
3176 /* front, rear, clfe, rear_surr */
3177 0x02, 0x03, 0x04, 0x05
3180 /* identical with ALC880 */
3181 #define alc882_adc_nids alc880_adc_nids
3182 #define alc882_adc_nids_alt alc880_adc_nids_alt
3185 /* FIXME: should be a matrix-type input source selection */
3187 static struct hda_input_mux alc882_capture_source
= {
3191 { "Front Mic", 0x1 },
3197 #define alc882_mux_enum_info alc_mux_enum_info
3198 #define alc882_mux_enum_get alc_mux_enum_get
3200 static int alc882_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
3202 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
3203 struct alc_spec
*spec
= codec
->spec
;
3204 const struct hda_input_mux
*imux
= spec
->input_mux
;
3205 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
3206 static hda_nid_t capture_mixers
[3] = { 0x24, 0x23, 0x22 };
3207 hda_nid_t nid
= capture_mixers
[adc_idx
];
3208 unsigned int *cur_val
= &spec
->cur_mux
[adc_idx
];
3209 unsigned int i
, idx
;
3211 idx
= ucontrol
->value
.enumerated
.item
[0];
3212 if (idx
>= imux
->num_items
)
3213 idx
= imux
->num_items
- 1;
3214 if (*cur_val
== idx
&& ! codec
->in_resume
)
3216 for (i
= 0; i
< imux
->num_items
; i
++) {
3217 unsigned int v
= (i
== idx
) ? 0x7000 : 0x7080;
3218 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3219 v
| (imux
->items
[i
].index
<< 8));
3228 static struct hda_verb alc882_sixstack_ch6_init
[] = {
3229 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
3230 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3231 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3232 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3239 static struct hda_verb alc882_sixstack_ch8_init
[] = {
3240 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3241 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3242 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3243 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3247 static struct hda_channel_mode alc882_sixstack_modes
[2] = {
3248 { 6, alc882_sixstack_ch6_init
},
3249 { 8, alc882_sixstack_ch8_init
},
3252 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3253 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3255 static struct snd_kcontrol_new alc882_base_mixer
[] = {
3256 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
3257 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT
),
3258 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT
),
3259 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT
),
3260 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT
),
3261 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
3262 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT
),
3263 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT
),
3264 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT
),
3265 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT
),
3266 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT
),
3267 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
3268 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
3269 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
3270 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
3271 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
3272 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
3273 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT
),
3274 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT
),
3275 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT
),
3276 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT
),
3277 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
3278 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
3279 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
3280 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
3281 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
3282 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
3284 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3285 /* .name = "Capture Source", */
3286 .name
= "Input Source",
3288 .info
= alc882_mux_enum_info
,
3289 .get
= alc882_mux_enum_get
,
3290 .put
= alc882_mux_enum_put
,
3295 static struct snd_kcontrol_new alc882_chmode_mixer
[] = {
3297 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3298 .name
= "Channel Mode",
3299 .info
= alc_ch_mode_info
,
3300 .get
= alc_ch_mode_get
,
3301 .put
= alc_ch_mode_put
,
3306 static struct hda_verb alc882_init_verbs
[] = {
3307 /* Front mixer: unmute input/output amp left and right (volume = 0) */
3308 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3309 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3310 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3312 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3313 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3314 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3316 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3317 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3318 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3320 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3321 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3322 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
3324 /* Front Pin: output 0 (0x0c) */
3325 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3326 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3327 {0x14, AC_VERB_SET_CONNECT_SEL
, 0x00},
3328 /* Rear Pin: output 1 (0x0d) */
3329 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3330 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3331 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x01},
3332 /* CLFE Pin: output 2 (0x0e) */
3333 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3334 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3335 {0x16, AC_VERB_SET_CONNECT_SEL
, 0x02},
3336 /* Side Pin: output 3 (0x0f) */
3337 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
},
3338 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3339 {0x17, AC_VERB_SET_CONNECT_SEL
, 0x03},
3340 /* Mic (rear) pin: input vref at 80% */
3341 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3342 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3343 /* Front Mic pin: input vref at 80% */
3344 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
},
3345 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3346 /* Line In pin: input */
3347 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3348 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
3349 /* Line-2 In: Headphone output (output 0 - 0x0c) */
3350 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
},
3351 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
3352 {0x1b, AC_VERB_SET_CONNECT_SEL
, 0x00},
3353 /* CD pin widget for input */
3354 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
},
3356 /* FIXME: use matrix-type input source selection */
3357 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3358 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3359 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3360 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3361 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3362 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3364 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3365 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3366 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3367 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3369 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3370 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
3371 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
3372 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
3373 /* ADC1: mute amp left and right */
3374 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3375 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3376 /* ADC2: mute amp left and right */
3377 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3378 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3379 /* ADC3: mute amp left and right */
3380 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
3381 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3387 * generic initialization of ADC, input mixers and output mixers
3389 static struct hda_verb alc882_auto_init_verbs
[] = {
3391 * Unmute ADC0-2 and set the default input to mic-in
3393 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3394 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3395 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3396 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3397 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3398 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3400 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3402 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3405 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3406 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3407 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3408 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
3409 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
3410 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
3413 * Set up output mixers (0x0c - 0x0f)
3415 /* set vol=0 to output mixers */
3416 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3417 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3418 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3419 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3420 /* set up input amps for analog loopback */
3421 /* Amp Indices: DAC = 0, mixer = 1 */
3422 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3423 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3424 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3425 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3426 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3427 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3428 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3429 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3430 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3431 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3433 /* FIXME: use matrix-type input source selection */
3434 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3435 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3436 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3437 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3438 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3439 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3441 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3442 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3443 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3444 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3446 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3447 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3448 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3449 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3454 /* capture mixer elements */
3455 static struct snd_kcontrol_new alc882_capture_alt_mixer
[] = {
3456 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
3457 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
3458 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT
),
3459 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT
),
3461 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3462 /* The multiple "Capture Source" controls confuse alsamixer
3463 * So call somewhat different..
3464 * FIXME: the controls appear in the "playback" view!
3466 /* .name = "Capture Source", */
3467 .name
= "Input Source",
3469 .info
= alc882_mux_enum_info
,
3470 .get
= alc882_mux_enum_get
,
3471 .put
= alc882_mux_enum_put
,
3476 static struct snd_kcontrol_new alc882_capture_mixer
[] = {
3477 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT
),
3478 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT
),
3479 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT
),
3480 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT
),
3481 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT
),
3482 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT
),
3484 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3485 /* The multiple "Capture Source" controls confuse alsamixer
3486 * So call somewhat different..
3487 * FIXME: the controls appear in the "playback" view!
3489 /* .name = "Capture Source", */
3490 .name
= "Input Source",
3492 .info
= alc882_mux_enum_info
,
3493 .get
= alc882_mux_enum_get
,
3494 .put
= alc882_mux_enum_put
,
3499 /* pcm configuration: identiacal with ALC880 */
3500 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
3501 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
3502 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
3503 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
3506 * configuration and preset
3508 static struct hda_board_config alc882_cfg_tbl
[] = {
3509 { .modelname
= "3stack-dig", .config
= ALC882_3ST_DIG
},
3510 { .modelname
= "6stack-dig", .config
= ALC882_6ST_DIG
},
3511 { .pci_subvendor
= 0x1462, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* MSI */
3512 { .pci_subvendor
= 0x105b, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* Foxconn */
3513 { .pci_subvendor
= 0x1019, .pci_subdevice
= 0x6668, .config
= ALC882_6ST_DIG
}, /* ECS */
3514 { .modelname
= "auto", .config
= ALC882_AUTO
},
3518 static struct alc_config_preset alc882_presets
[] = {
3519 [ALC882_3ST_DIG
] = {
3520 .mixers
= { alc882_base_mixer
},
3521 .init_verbs
= { alc882_init_verbs
},
3522 .num_dacs
= ARRAY_SIZE(alc882_dac_nids
),
3523 .dac_nids
= alc882_dac_nids
,
3524 .dig_out_nid
= ALC882_DIGOUT_NID
,
3525 .num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
),
3526 .adc_nids
= alc882_adc_nids
,
3527 .dig_in_nid
= ALC882_DIGIN_NID
,
3528 .num_channel_mode
= ARRAY_SIZE(alc882_ch_modes
),
3529 .channel_mode
= alc882_ch_modes
,
3530 .input_mux
= &alc882_capture_source
,
3532 [ALC882_6ST_DIG
] = {
3533 .mixers
= { alc882_base_mixer
, alc882_chmode_mixer
},
3534 .init_verbs
= { alc882_init_verbs
},
3535 .num_dacs
= ARRAY_SIZE(alc882_dac_nids
),
3536 .dac_nids
= alc882_dac_nids
,
3537 .dig_out_nid
= ALC882_DIGOUT_NID
,
3538 .num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
),
3539 .adc_nids
= alc882_adc_nids
,
3540 .dig_in_nid
= ALC882_DIGIN_NID
,
3541 .num_channel_mode
= ARRAY_SIZE(alc882_sixstack_modes
),
3542 .channel_mode
= alc882_sixstack_modes
,
3543 .input_mux
= &alc882_capture_source
,
3549 * BIOS auto configuration
3551 static void alc882_auto_set_output_and_unmute(struct hda_codec
*codec
,
3552 hda_nid_t nid
, int pin_type
,
3556 struct alc_spec
*spec
= codec
->spec
;
3559 if (spec
->multiout
.dac_nids
[dac_idx
] == 0x25)
3562 idx
= spec
->multiout
.dac_nids
[dac_idx
] - 2;
3564 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
3565 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
3566 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_CONNECT_SEL
, idx
);
3570 static void alc882_auto_init_multi_out(struct hda_codec
*codec
)
3572 struct alc_spec
*spec
= codec
->spec
;
3575 for (i
= 0; i
<= HDA_SIDE
; i
++) {
3576 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
3578 alc882_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
3582 static void alc882_auto_init_hp_out(struct hda_codec
*codec
)
3584 struct alc_spec
*spec
= codec
->spec
;
3587 pin
= spec
->autocfg
.hp_pin
;
3588 if (pin
) /* connect to front */
3589 alc882_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0); /* use dac 0 */
3592 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
3593 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
3595 static void alc882_auto_init_analog_input(struct hda_codec
*codec
)
3597 struct alc_spec
*spec
= codec
->spec
;
3600 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
3601 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
3602 if (alc882_is_input_pin(nid
)) {
3603 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
3604 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
3605 if (nid
!= ALC882_PIN_CD_NID
)
3606 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
3612 /* almost identical with ALC880 parser... */
3613 static int alc882_parse_auto_config(struct hda_codec
*codec
)
3615 struct alc_spec
*spec
= codec
->spec
;
3616 int err
= alc880_parse_auto_config(codec
);
3621 /* hack - override the init verbs */
3622 spec
->init_verbs
[0] = alc882_auto_init_verbs
;
3626 /* init callback for auto-configuration model -- overriding the default init */
3627 static int alc882_auto_init(struct hda_codec
*codec
)
3630 alc882_auto_init_multi_out(codec
);
3631 alc882_auto_init_hp_out(codec
);
3632 alc882_auto_init_analog_input(codec
);
3637 * ALC882 Headphone poll in 3.5.1a or 3.5.2
3640 static int patch_alc882(struct hda_codec
*codec
)
3642 struct alc_spec
*spec
;
3643 int err
, board_config
;
3645 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
3651 board_config
= snd_hda_check_board_config(codec
, alc882_cfg_tbl
);
3653 if (board_config
< 0 || board_config
>= ALC882_MODEL_LAST
) {
3654 printk(KERN_INFO
"hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
3655 board_config
= ALC882_AUTO
;
3658 if (board_config
== ALC882_AUTO
) {
3659 /* automatic parse from the BIOS config */
3660 err
= alc882_parse_auto_config(codec
);
3665 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3666 board_config
= ALC882_3ST_DIG
;
3670 if (board_config
!= ALC882_AUTO
)
3671 setup_preset(spec
, &alc882_presets
[board_config
]);
3673 spec
->stream_name_analog
= "ALC882 Analog";
3674 spec
->stream_analog_playback
= &alc882_pcm_analog_playback
;
3675 spec
->stream_analog_capture
= &alc882_pcm_analog_capture
;
3677 spec
->stream_name_digital
= "ALC882 Digital";
3678 spec
->stream_digital_playback
= &alc882_pcm_digital_playback
;
3679 spec
->stream_digital_capture
= &alc882_pcm_digital_capture
;
3681 if (! spec
->adc_nids
&& spec
->input_mux
) {
3682 /* check whether NID 0x07 is valid */
3683 unsigned int wcap
= get_wcaps(codec
, 0x07);
3684 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
3685 if (wcap
!= AC_WID_AUD_IN
) {
3686 spec
->adc_nids
= alc882_adc_nids_alt
;
3687 spec
->num_adc_nids
= ARRAY_SIZE(alc882_adc_nids_alt
);
3688 spec
->mixers
[spec
->num_mixers
] = alc882_capture_alt_mixer
;
3691 spec
->adc_nids
= alc882_adc_nids
;
3692 spec
->num_adc_nids
= ARRAY_SIZE(alc882_adc_nids
);
3693 spec
->mixers
[spec
->num_mixers
] = alc882_capture_mixer
;
3698 codec
->patch_ops
= alc_patch_ops
;
3699 if (board_config
== ALC882_AUTO
)
3700 codec
->patch_ops
.init
= alc882_auto_init
;
3709 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
3710 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
3712 #define alc262_dac_nids alc260_dac_nids
3713 #define alc262_adc_nids alc882_adc_nids
3714 #define alc262_adc_nids_alt alc882_adc_nids_alt
3716 #define alc262_modes alc260_modes
3717 #define alc262_capture_source alc882_capture_source
3719 static struct snd_kcontrol_new alc262_base_mixer
[] = {
3720 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT
),
3721 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT
),
3722 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT
),
3723 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT
),
3724 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT
),
3725 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT
),
3726 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT
),
3727 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT
),
3728 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT
),
3729 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT
),
3730 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3731 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3732 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT
),
3733 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT
),
3734 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT
),
3735 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT
),
3736 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
3737 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
3739 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
3740 .name
= "Capture Source",
3742 .info
= alc882_mux_enum_info
,
3743 .get
= alc882_mux_enum_get
,
3744 .put
= alc882_mux_enum_put
,
3749 #define alc262_capture_mixer alc882_capture_mixer
3750 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
3753 * generic initialization of ADC, input mixers and output mixers
3755 static struct hda_verb alc262_init_verbs
[] = {
3757 * Unmute ADC0-2 and set the default input to mic-in
3759 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3760 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3761 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3762 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3763 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3764 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3766 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3768 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3771 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3772 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3773 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3774 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
3775 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
3776 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
3779 * Set up output mixers (0x0c - 0x0e)
3781 /* set vol=0 to output mixers */
3782 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3783 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3784 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3785 /* set up input amps for analog loopback */
3786 /* Amp Indices: DAC = 0, mixer = 1 */
3787 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3788 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3789 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3790 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3791 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3792 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3794 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
3795 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0},
3796 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
3797 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24},
3798 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
3799 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
3801 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
3802 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
3803 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
3804 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
3805 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, 0x0000},
3807 {0x14, AC_VERB_SET_CONNECT_SEL
, 0x00},
3808 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x01},
3810 /* FIXME: use matrix-type input source selection */
3811 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3812 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3813 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3814 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3815 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3816 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3818 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3819 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3820 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3821 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3823 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3824 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3825 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3826 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3831 /* add playback controls from the parsed DAC table */
3832 static int alc262_auto_create_multi_out_ctls(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
3837 spec
->multiout
.num_dacs
= 1; /* only use one dac */
3838 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
3839 spec
->multiout
.dac_nids
[0] = 2;
3841 nid
= cfg
->line_out_pins
[0];
3843 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Front Playback Volume",
3844 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
3846 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Front Playback Switch",
3847 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
3851 nid
= cfg
->speaker_pin
;
3854 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Speaker Playback Volume",
3855 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT
))) < 0)
3857 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Speaker Playback Switch",
3858 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
3861 if (! cfg
->line_out_pins
[0])
3862 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Speaker Playback Volume",
3863 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
3865 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Speaker Playback Switch",
3866 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
3872 /* spec->multiout.hp_nid = 2; */
3874 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Headphone Playback Volume",
3875 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT
))) < 0)
3877 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
3878 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
3881 if (! cfg
->line_out_pins
[0])
3882 if ((err
= add_control(spec
, ALC_CTL_WIDGET_VOL
, "Headphone Playback Volume",
3883 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT
))) < 0)
3885 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
3886 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
3893 /* identical with ALC880 */
3894 #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
3897 * generic initialization of ADC, input mixers and output mixers
3899 static struct hda_verb alc262_volume_init_verbs
[] = {
3901 * Unmute ADC0-2 and set the default input to mic-in
3903 {0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
3904 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3905 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
3906 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3907 {0x09, AC_VERB_SET_CONNECT_SEL
, 0x00},
3908 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3910 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3912 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3915 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3916 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3917 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3918 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
3919 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
3920 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
3923 * Set up output mixers (0x0c - 0x0f)
3925 /* set vol=0 to output mixers */
3926 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3927 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3928 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
3930 /* set up input amps for analog loopback */
3931 /* Amp Indices: DAC = 0, mixer = 1 */
3932 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3933 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3934 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3935 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3936 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
3937 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
3939 /* FIXME: use matrix-type input source selection */
3940 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3941 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3942 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3943 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3944 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3945 {0x24, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3947 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3948 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3949 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3950 {0x23, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3952 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x00 << 8))},
3953 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x03 << 8))},
3954 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8))},
3955 {0x22, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x04 << 8))},
3960 /* pcm configuration: identiacal with ALC880 */
3961 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
3962 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
3963 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
3964 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
3967 * BIOS auto configuration
3969 static int alc262_parse_auto_config(struct hda_codec
*codec
)
3971 struct alc_spec
*spec
= codec
->spec
;
3973 static hda_nid_t alc262_ignore
[] = { 0x1d, 0 };
3975 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
3976 alc262_ignore
)) < 0)
3978 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
3979 ! spec
->autocfg
.hp_pin
)
3980 return 0; /* can't find valid BIOS pin config */
3981 if ((err
= alc262_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
3982 (err
= alc262_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
3985 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
3987 if (spec
->autocfg
.dig_out_pin
)
3988 spec
->multiout
.dig_out_nid
= ALC262_DIGOUT_NID
;
3989 if (spec
->autocfg
.dig_in_pin
)
3990 spec
->dig_in_nid
= ALC262_DIGIN_NID
;
3992 if (spec
->kctl_alloc
)
3993 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
3995 spec
->init_verbs
[spec
->num_init_verbs
++] = alc262_volume_init_verbs
;
3996 spec
->input_mux
= &spec
->private_imux
;
4001 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
4002 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
4003 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
4006 /* init callback for auto-configuration model -- overriding the default init */
4007 static int alc262_auto_init(struct hda_codec
*codec
)
4010 alc262_auto_init_multi_out(codec
);
4011 alc262_auto_init_hp_out(codec
);
4012 alc262_auto_init_analog_input(codec
);
4017 * configuration and preset
4019 static struct hda_board_config alc262_cfg_tbl
[] = {
4020 { .modelname
= "basic", .config
= ALC262_BASIC
},
4021 { .modelname
= "auto", .config
= ALC262_AUTO
},
4025 static struct alc_config_preset alc262_presets
[] = {
4027 .mixers
= { alc262_base_mixer
},
4028 .init_verbs
= { alc262_init_verbs
},
4029 .num_dacs
= ARRAY_SIZE(alc262_dac_nids
),
4030 .dac_nids
= alc262_dac_nids
,
4032 .num_channel_mode
= ARRAY_SIZE(alc262_modes
),
4033 .channel_mode
= alc262_modes
,
4034 .input_mux
= &alc262_capture_source
,
4038 static int patch_alc262(struct hda_codec
*codec
)
4040 struct alc_spec
*spec
;
4044 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
4050 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
4053 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_COEF_INDEX
, 7);
4054 tmp
= snd_hda_codec_read(codec
, 0x20, 0, AC_VERB_GET_PROC_COEF
, 0);
4055 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_COEF_INDEX
, 7);
4056 snd_hda_codec_write(codec
, 0x1a, 0, AC_VERB_SET_PROC_COEF
, tmp
| 0x80);
4060 board_config
= snd_hda_check_board_config(codec
, alc262_cfg_tbl
);
4061 if (board_config
< 0 || board_config
>= ALC262_MODEL_LAST
) {
4062 printk(KERN_INFO
"hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4063 board_config
= ALC262_AUTO
;
4066 if (board_config
== ALC262_AUTO
) {
4067 /* automatic parse from the BIOS config */
4068 err
= alc262_parse_auto_config(codec
);
4073 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4074 board_config
= ALC262_BASIC
;
4078 if (board_config
!= ALC262_AUTO
)
4079 setup_preset(spec
, &alc262_presets
[board_config
]);
4081 spec
->stream_name_analog
= "ALC262 Analog";
4082 spec
->stream_analog_playback
= &alc262_pcm_analog_playback
;
4083 spec
->stream_analog_capture
= &alc262_pcm_analog_capture
;
4085 spec
->stream_name_digital
= "ALC262 Digital";
4086 spec
->stream_digital_playback
= &alc262_pcm_digital_playback
;
4087 spec
->stream_digital_capture
= &alc262_pcm_digital_capture
;
4089 if (! spec
->adc_nids
&& spec
->input_mux
) {
4090 /* check whether NID 0x07 is valid */
4091 unsigned int wcap
= get_wcaps(codec
, 0x07);
4093 wcap
= (wcap
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
; /* get type */
4094 if (wcap
!= AC_WID_AUD_IN
) {
4095 spec
->adc_nids
= alc262_adc_nids_alt
;
4096 spec
->num_adc_nids
= ARRAY_SIZE(alc262_adc_nids_alt
);
4097 spec
->mixers
[spec
->num_mixers
] = alc262_capture_alt_mixer
;
4100 spec
->adc_nids
= alc262_adc_nids
;
4101 spec
->num_adc_nids
= ARRAY_SIZE(alc262_adc_nids
);
4102 spec
->mixers
[spec
->num_mixers
] = alc262_capture_mixer
;
4107 codec
->patch_ops
= alc_patch_ops
;
4108 if (board_config
== ALC262_AUTO
)
4109 codec
->patch_ops
.init
= alc262_auto_init
;
4116 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4120 * set the path ways for 2 channel output
4121 * need to set the codec line out and mic 1 pin widgets to inputs
4123 static struct hda_verb alc861_threestack_ch2_init
[] = {
4124 /* set pin widget 1Ah (line in) for input */
4125 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4126 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4127 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4129 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c },
4130 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x01 << 8)) }, //mic
4131 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7000 | (0x02 << 8)) }, //line in
4136 * need to set the codec line out and mic 1 pin widgets to outputs
4138 static struct hda_verb alc861_threestack_ch6_init
[] = {
4139 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4140 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4141 /* set pin widget 18h (mic1) for output (CLFE)*/
4142 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4144 { 0x0c, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4145 { 0x0d, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4147 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb080 },
4148 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x01 << 8)) }, //mic
4149 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE
, (0x7080 | (0x02 << 8)) }, //line in
4153 static struct hda_channel_mode alc861_threestack_modes
[2] = {
4154 { 2, alc861_threestack_ch2_init
},
4155 { 6, alc861_threestack_ch6_init
},
4160 static struct snd_kcontrol_new alc861_base_mixer
[] = {
4161 /* output mixer control */
4162 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
4163 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
4164 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT
),
4165 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT
),
4166 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT
),
4168 /*Input mixer control */
4169 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4170 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4171 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT
),
4172 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT
),
4173 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT
),
4174 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT
),
4175 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT
),
4176 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT
),
4177 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT
),
4178 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT
),
4180 /* Capture mixer control */
4181 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
4182 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
4184 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4185 .name
= "Capture Source",
4187 .info
= alc_mux_enum_info
,
4188 .get
= alc_mux_enum_get
,
4189 .put
= alc_mux_enum_put
,
4194 static struct snd_kcontrol_new alc861_3ST_mixer
[] = {
4195 /* output mixer control */
4196 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT
),
4197 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT
),
4198 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT
),
4199 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT
),
4200 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4202 /* Input mixer control */
4203 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4204 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4205 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT
),
4206 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT
),
4207 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT
),
4208 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT
),
4209 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT
),
4210 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT
),
4211 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT
),
4212 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT
),
4214 /* Capture mixer control */
4215 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
4216 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
4218 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4219 .name
= "Capture Source",
4221 .info
= alc_mux_enum_info
,
4222 .get
= alc_mux_enum_get
,
4223 .put
= alc_mux_enum_put
,
4226 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4227 .name
= "Channel Mode",
4228 .info
= alc_ch_mode_info
,
4229 .get
= alc_ch_mode_get
,
4230 .put
= alc_ch_mode_put
,
4231 .private_value
= ARRAY_SIZE(alc861_threestack_modes
),
4237 * generic initialization of ADC, input mixers and output mixers
4239 static struct hda_verb alc861_base_init_verbs
[] = {
4241 * Unmute ADC0 and set the default input to mic-in
4243 /* port-A for surround (rear panel) */
4244 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4245 { 0x0e, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4246 /* port-B for mic-in (rear panel) with vref */
4247 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4248 /* port-C for line-in (rear panel) */
4249 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4250 /* port-D for Front */
4251 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4252 { 0x0b, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4253 /* port-E for HP out (front panel) */
4254 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
4255 /* route front PCM to HP */
4256 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x01 },
4257 /* port-F for mic-in (front panel) with vref */
4258 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4259 /* port-G for CLFE (rear panel) */
4260 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4261 { 0x1f, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4262 /* port-H for side (rear panel) */
4263 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4264 { 0x20, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4266 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4267 /* route front mic to ADC1*/
4268 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4269 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4271 /* Unmute DAC0~3 & spdif out*/
4272 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4273 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4274 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4275 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4276 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4278 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4279 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4280 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4281 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4282 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4284 /* Unmute Stereo Mixer 15 */
4285 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4286 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4287 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4288 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c }, //Output 0~12 step
4290 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4291 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4292 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4293 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4294 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4295 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4296 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4297 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4298 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4299 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4304 static struct hda_verb alc861_threestack_init_verbs
[] = {
4306 * Unmute ADC0 and set the default input to mic-in
4308 /* port-A for surround (rear panel) */
4309 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4310 /* port-B for mic-in (rear panel) with vref */
4311 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4312 /* port-C for line-in (rear panel) */
4313 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4314 /* port-D for Front */
4315 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40 },
4316 { 0x0b, AC_VERB_SET_CONNECT_SEL
, 0x00 },
4317 /* port-E for HP out (front panel) */
4318 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0xc0 },
4319 /* route front PCM to HP */
4320 { 0x0f, AC_VERB_SET_CONNECT_SEL
, 0x01 },
4321 /* port-F for mic-in (front panel) with vref */
4322 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x24 },
4323 /* port-G for CLFE (rear panel) */
4324 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4325 /* port-H for side (rear panel) */
4326 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x00 },
4328 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20 },
4329 /* route front mic to ADC1*/
4330 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00},
4331 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4332 /* Unmute DAC0~3 & spdif out*/
4333 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4334 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4335 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4336 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4337 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4339 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4340 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4341 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4342 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4343 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4345 /* Unmute Stereo Mixer 15 */
4346 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4347 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4348 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4349 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c }, //Output 0~12 step
4351 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4352 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4353 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4354 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4355 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4356 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4357 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4358 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4359 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4360 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4364 * generic initialization of ADC, input mixers and output mixers
4366 static struct hda_verb alc861_auto_init_verbs
[] = {
4368 * Unmute ADC0 and set the default input to mic-in
4370 // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4371 {0x08, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4373 /* Unmute DAC0~3 & spdif out*/
4374 {0x03, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4375 {0x04, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4376 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4377 {0x06, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
},
4378 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
},
4380 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4381 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4382 {0x014, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4383 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4384 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4386 /* Unmute Stereo Mixer 15 */
4387 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4388 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4389 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4390 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, 0xb00c},
4392 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4393 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4394 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4395 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4396 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4397 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4398 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
4399 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
4401 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4402 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4403 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4404 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
4405 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)},
4406 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
4407 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
4408 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
4410 {0x08, AC_VERB_SET_CONNECT_SEL
, 0x00}, // set Mic 1
4415 /* pcm configuration: identiacal with ALC880 */
4416 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
4417 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
4418 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
4419 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
4422 #define ALC861_DIGOUT_NID 0x07
4424 static struct hda_channel_mode alc861_8ch_modes
[1] = {
4428 static hda_nid_t alc861_dac_nids
[4] = {
4429 /* front, surround, clfe, side */
4430 0x03, 0x06, 0x05, 0x04
4433 static hda_nid_t alc861_adc_nids
[1] = {
4438 static struct hda_input_mux alc861_capture_source
= {
4442 { "Front Mic", 0x3 },
4449 /* fill in the dac_nids table from the parsed pin configuration */
4450 static int alc861_auto_fill_dac_nids(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
4455 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
4456 for (i
= 0; i
< cfg
->line_outs
; i
++) {
4457 nid
= cfg
->line_out_pins
[i
];
4459 if (i
>= ARRAY_SIZE(alc861_dac_nids
))
4461 spec
->multiout
.dac_nids
[i
] = alc861_dac_nids
[i
];
4464 spec
->multiout
.num_dacs
= cfg
->line_outs
;
4468 /* add playback controls from the parsed DAC table */
4469 static int alc861_auto_create_multi_out_ctls(struct alc_spec
*spec
,
4470 const struct auto_pin_cfg
*cfg
)
4473 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
4477 for (i
= 0; i
< cfg
->line_outs
; i
++) {
4478 nid
= spec
->multiout
.dac_nids
[i
];
4483 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "Center Playback Switch",
4484 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
4486 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, "LFE Playback Switch",
4487 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
4490 for (idx
= 0; idx
< ARRAY_SIZE(alc861_dac_nids
) - 1; idx
++)
4491 if (nid
== alc861_dac_nids
[idx
])
4493 sprintf(name
, "%s Playback Switch", chname
[idx
]);
4494 if ((err
= add_control(spec
, ALC_CTL_BIND_MUTE
, name
,
4495 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
4502 static int alc861_auto_create_hp_ctls(struct alc_spec
*spec
, hda_nid_t pin
)
4510 if ((pin
>= 0x0b && pin
<= 0x10) || pin
== 0x1f || pin
== 0x20) {
4512 if ((err
= add_control(spec
, ALC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
4513 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
4515 spec
->multiout
.hp_nid
= nid
;
4520 /* create playback/capture controls for input pins */
4521 static int alc861_auto_create_analog_input_ctls(struct alc_spec
*spec
, const struct auto_pin_cfg
*cfg
)
4523 struct hda_input_mux
*imux
= &spec
->private_imux
;
4524 int i
, err
, idx
, idx1
;
4526 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
4527 switch(cfg
->input_pins
[i
]) {
4552 err
= new_analog_input(spec
, cfg
->input_pins
[i
],
4553 auto_pin_cfg_labels
[i
], idx
, 0x15);
4557 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
4558 imux
->items
[imux
->num_items
].index
= idx1
;
4564 static struct snd_kcontrol_new alc861_capture_mixer
[] = {
4565 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT
),
4566 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT
),
4569 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
4570 /* The multiple "Capture Source" controls confuse alsamixer
4571 * So call somewhat different..
4572 *FIXME: the controls appear in the "playback" view!
4574 /* .name = "Capture Source", */
4575 .name
= "Input Source",
4577 .info
= alc_mux_enum_info
,
4578 .get
= alc_mux_enum_get
,
4579 .put
= alc_mux_enum_put
,
4584 static void alc861_auto_set_output_and_unmute(struct hda_codec
*codec
, hda_nid_t nid
,
4585 int pin_type
, int dac_idx
)
4589 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
4590 snd_hda_codec_write(codec
, dac_idx
, 0, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
);
4594 static void alc861_auto_init_multi_out(struct hda_codec
*codec
)
4596 struct alc_spec
*spec
= codec
->spec
;
4599 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
4600 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
4602 alc861_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, spec
->multiout
.dac_nids
[i
]);
4606 static void alc861_auto_init_hp_out(struct hda_codec
*codec
)
4608 struct alc_spec
*spec
= codec
->spec
;
4611 pin
= spec
->autocfg
.hp_pin
;
4612 if (pin
) /* connect to front */
4613 alc861_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, spec
->multiout
.dac_nids
[0]);
4616 static void alc861_auto_init_analog_input(struct hda_codec
*codec
)
4618 struct alc_spec
*spec
= codec
->spec
;
4621 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
4622 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
4623 if ((nid
>=0x0c) && (nid
<=0x11)) {
4624 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
4625 i
<= AUTO_PIN_FRONT_MIC
? PIN_VREF80
: PIN_IN
);
4630 /* parse the BIOS configuration and set up the alc_spec */
4631 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4632 static int alc861_parse_auto_config(struct hda_codec
*codec
)
4634 struct alc_spec
*spec
= codec
->spec
;
4636 static hda_nid_t alc861_ignore
[] = { 0x1d, 0 };
4638 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
,
4639 alc861_ignore
)) < 0)
4641 if (! spec
->autocfg
.line_outs
&& ! spec
->autocfg
.speaker_pin
&&
4642 ! spec
->autocfg
.hp_pin
)
4643 return 0; /* can't find valid BIOS pin config */
4645 if ((err
= alc861_auto_fill_dac_nids(spec
, &spec
->autocfg
)) < 0 ||
4646 (err
= alc861_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
4647 (err
= alc861_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pin
)) < 0 ||
4648 (err
= alc861_auto_create_analog_input_ctls(spec
, &spec
->autocfg
)) < 0)
4651 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
4653 if (spec
->autocfg
.dig_out_pin
)
4654 spec
->multiout
.dig_out_nid
= ALC861_DIGOUT_NID
;
4656 if (spec
->kctl_alloc
)
4657 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
4659 spec
->init_verbs
[spec
->num_init_verbs
++] = alc861_auto_init_verbs
;
4661 spec
->input_mux
= &spec
->private_imux
;
4663 spec
->adc_nids
= alc861_adc_nids
;
4664 spec
->num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
);
4665 spec
->mixers
[spec
->num_mixers
] = alc861_capture_mixer
;
4671 /* init callback for auto-configuration model -- overriding the default init */
4672 static int alc861_auto_init(struct hda_codec
*codec
)
4675 alc861_auto_init_multi_out(codec
);
4676 alc861_auto_init_hp_out(codec
);
4677 alc861_auto_init_analog_input(codec
);
4684 * configuration and preset
4686 static struct hda_board_config alc861_cfg_tbl
[] = {
4687 { .modelname
= "3stack", .config
= ALC861_3ST
},
4688 { .pci_subvendor
= 0x8086, .pci_subdevice
= 0xd600, .config
= ALC861_3ST
},
4689 { .modelname
= "3stack-dig", .config
= ALC861_3ST_DIG
},
4690 { .modelname
= "6stack-dig", .config
= ALC861_6ST_DIG
},
4691 { .modelname
= "auto", .config
= ALC861_AUTO
},
4695 static struct alc_config_preset alc861_presets
[] = {
4697 .mixers
= { alc861_3ST_mixer
},
4698 .init_verbs
= { alc861_threestack_init_verbs
},
4699 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
4700 .dac_nids
= alc861_dac_nids
,
4701 .num_channel_mode
= ARRAY_SIZE(alc861_threestack_modes
),
4702 .channel_mode
= alc861_threestack_modes
,
4703 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
4704 .adc_nids
= alc861_adc_nids
,
4705 .input_mux
= &alc861_capture_source
,
4707 [ALC861_3ST_DIG
] = {
4708 .mixers
= { alc861_base_mixer
},
4709 .init_verbs
= { alc861_threestack_init_verbs
},
4710 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
4711 .dac_nids
= alc861_dac_nids
,
4712 .dig_out_nid
= ALC861_DIGOUT_NID
,
4713 .num_channel_mode
= ARRAY_SIZE(alc861_threestack_modes
),
4714 .channel_mode
= alc861_threestack_modes
,
4715 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
4716 .adc_nids
= alc861_adc_nids
,
4717 .input_mux
= &alc861_capture_source
,
4719 [ALC861_6ST_DIG
] = {
4720 .mixers
= { alc861_base_mixer
},
4721 .init_verbs
= { alc861_base_init_verbs
},
4722 .num_dacs
= ARRAY_SIZE(alc861_dac_nids
),
4723 .dac_nids
= alc861_dac_nids
,
4724 .dig_out_nid
= ALC861_DIGOUT_NID
,
4725 .num_channel_mode
= ARRAY_SIZE(alc861_8ch_modes
),
4726 .channel_mode
= alc861_8ch_modes
,
4727 .num_adc_nids
= ARRAY_SIZE(alc861_adc_nids
),
4728 .adc_nids
= alc861_adc_nids
,
4729 .input_mux
= &alc861_capture_source
,
4734 static int patch_alc861(struct hda_codec
*codec
)
4736 struct alc_spec
*spec
;
4740 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
4746 board_config
= snd_hda_check_board_config(codec
, alc861_cfg_tbl
);
4747 if (board_config
< 0 || board_config
>= ALC861_MODEL_LAST
) {
4748 printk(KERN_INFO
"hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
4749 board_config
= ALC861_AUTO
;
4752 if (board_config
== ALC861_AUTO
) {
4753 /* automatic parse from the BIOS config */
4754 err
= alc861_parse_auto_config(codec
);
4759 printk(KERN_INFO
"hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4760 board_config
= ALC861_3ST_DIG
;
4764 if (board_config
!= ALC861_AUTO
)
4765 setup_preset(spec
, &alc861_presets
[board_config
]);
4767 spec
->stream_name_analog
= "ALC861 Analog";
4768 spec
->stream_analog_playback
= &alc861_pcm_analog_playback
;
4769 spec
->stream_analog_capture
= &alc861_pcm_analog_capture
;
4771 spec
->stream_name_digital
= "ALC861 Digital";
4772 spec
->stream_digital_playback
= &alc861_pcm_digital_playback
;
4773 spec
->stream_digital_capture
= &alc861_pcm_digital_capture
;
4775 codec
->patch_ops
= alc_patch_ops
;
4776 if (board_config
== ALC861_AUTO
)
4777 codec
->patch_ops
.init
= alc861_auto_init
;
4785 struct hda_codec_preset snd_hda_preset_realtek
[] = {
4786 { .id
= 0x10ec0260, .name
= "ALC260", .patch
= patch_alc260
},
4787 { .id
= 0x10ec0262, .name
= "ALC262", .patch
= patch_alc262
},
4788 { .id
= 0x10ec0880, .name
= "ALC880", .patch
= patch_alc880
},
4789 { .id
= 0x10ec0882, .name
= "ALC882", .patch
= patch_alc882
},
4790 { .id
= 0x10ec0883, .name
= "ALC883", .patch
= patch_alc882
},
4791 { .id
= 0x10ec0885, .name
= "ALC885", .patch
= patch_alc882
},
4792 { .id
= 0x10ec0861, .name
= "ALC861", .patch
= patch_alc861
},