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>
9 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <sound/driver.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/slab.h>
30 #include <linux/pci.h>
31 #include <sound/core.h>
32 #include "hda_codec.h"
33 #include "hda_local.h"
36 /* ALC880 board config type */
54 #ifdef CONFIG_SND_DEBUG
58 ALC880_MODEL_LAST /* last tag */
67 #ifdef CONFIG_SND_DEBUG
71 ALC260_MODEL_LAST /* last tag */
78 ALC262_MODEL_LAST /* last tag */
99 #define GPIO_MASK 0x03
102 /* codec parameterization */
103 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
104 unsigned int num_mixers;
106 const struct hda_verb *init_verbs[5]; /* initialization verbs
107 * don't forget NULL termination!
109 unsigned int num_init_verbs;
111 char *stream_name_analog; /* analog PCM stream */
112 struct hda_pcm_stream *stream_analog_playback;
113 struct hda_pcm_stream *stream_analog_capture;
115 char *stream_name_digital; /* digital PCM stream */
116 struct hda_pcm_stream *stream_digital_playback;
117 struct hda_pcm_stream *stream_digital_capture;
120 struct hda_multi_out multiout; /* playback set-up
121 * max_channels, dacs must be set
122 * dig_out_nid and hp_nid are optional
126 unsigned int num_adc_nids;
128 hda_nid_t dig_in_nid; /* digital-in NID; optional */
131 const struct hda_input_mux *input_mux;
132 unsigned int cur_mux[3];
135 const struct hda_channel_mode *channel_mode;
136 int num_channel_mode;
138 /* PCM information */
139 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
141 /* dynamic controls, init_verbs and input_mux */
142 struct auto_pin_cfg autocfg;
143 unsigned int num_kctl_alloc, num_kctl_used;
144 struct snd_kcontrol_new *kctl_alloc;
145 struct hda_input_mux private_imux;
146 hda_nid_t private_dac_nids[5];
150 * configuration template - to be copied to the spec instance
152 struct alc_config_preset {
153 struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */
154 const struct hda_verb *init_verbs[5];
155 unsigned int num_dacs;
157 hda_nid_t dig_out_nid; /* optional */
158 hda_nid_t hp_nid; /* optional */
159 unsigned int num_adc_nids;
161 hda_nid_t dig_in_nid;
162 unsigned int num_channel_mode;
163 const struct hda_channel_mode *channel_mode;
164 const struct hda_input_mux *input_mux;
171 static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
173 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
174 struct alc_spec *spec = codec->spec;
175 return snd_hda_input_mux_info(spec->input_mux, uinfo);
178 static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
180 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
181 struct alc_spec *spec = codec->spec;
182 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
184 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
188 static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
190 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
191 struct alc_spec *spec = codec->spec;
192 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
193 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
194 spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
199 * channel mode setting
201 static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
203 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
204 struct alc_spec *spec = codec->spec;
205 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
206 spec->num_channel_mode);
209 static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
211 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
212 struct alc_spec *spec = codec->spec;
213 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
214 spec->num_channel_mode, spec->multiout.max_channels);
217 static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
219 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
220 struct alc_spec *spec = codec->spec;
221 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
222 spec->num_channel_mode, &spec->multiout.max_channels);
226 * Control the mode of pin widget settings via the mixer. "pc" is used
227 * instead of "%" to avoid consequences of accidently treating the % as
228 * being part of a format specifier. Maximum allowed length of a value is
229 * 63 characters plus NULL terminator.
231 * Note: some retasking pin complexes seem to ignore requests for input
232 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
233 * are requested. Therefore order this list so that this behaviour will not
234 * cause problems when mixer clients move through the enum sequentially.
235 * NIDs 0x0f and 0x10 have been observed to have this behaviour.
237 static char *alc_pin_mode_names[] = {
238 "Mic 50pc bias", "Mic 80pc bias",
239 "Line in", "Line out", "Headphone out",
241 static unsigned char alc_pin_mode_values[] = {
242 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
244 /* The control can present all 5 options, or it can limit the options based
245 * in the pin being assumed to be exclusively an input or an output pin.
247 #define ALC_PIN_DIR_IN 0x00
248 #define ALC_PIN_DIR_OUT 0x01
249 #define ALC_PIN_DIR_INOUT 0x02
251 /* Info about the pin modes supported by the three different pin directions.
252 * For each direction the minimum and maximum values are given.
254 static signed char alc_pin_mode_dir_info[3][2] = {
255 { 0, 2 }, /* ALC_PIN_DIR_IN */
256 { 3, 4 }, /* ALC_PIN_DIR_OUT */
257 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
259 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
260 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
261 #define alc_pin_mode_n_items(_dir) \
262 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
264 static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
266 unsigned int item_num = uinfo->value.enumerated.item;
267 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
269 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
271 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
273 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
274 item_num = alc_pin_mode_min(dir);
275 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
279 static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
282 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
283 hda_nid_t nid = kcontrol->private_value & 0xffff;
284 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
285 long *valp = ucontrol->value.integer.value;
286 unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
288 /* Find enumerated value for current pinctl setting */
289 i = alc_pin_mode_min(dir);
290 while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir))
292 *valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir);
296 static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
299 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
300 hda_nid_t nid = kcontrol->private_value & 0xffff;
301 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
302 long val = *ucontrol->value.integer.value;
303 unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
305 if (val<alc_pin_mode_min(dir) || val>alc_pin_mode_max(dir))
306 val = alc_pin_mode_min(dir);
308 change = pinctl != alc_pin_mode_values[val];
310 /* Set pin mode to that requested */
311 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
312 alc_pin_mode_values[val]);
314 /* Also enable the retasking pin's input/output as required
315 * for the requested pin mode. Enum values of 2 or less are
318 * Dynamically switching the input/output buffers probably
319 * reduces noise slightly, particularly on input. However,
320 * havingboth input and output buffers enabled
321 * simultaneously doesn't seem to be problematic.
324 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
326 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
329 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
331 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
338 #define ALC_PIN_MODE(xname, nid, dir) \
339 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
340 .info = alc_pin_mode_info, \
341 .get = alc_pin_mode_get, \
342 .put = alc_pin_mode_put, \
343 .private_value = nid | (dir<<16) }
345 /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
346 * together using a mask with more than one bit set. This control is
347 * currently used only by the ALC260 test model. At this stage they are not
348 * needed for any "production" models.
350 #ifdef CONFIG_SND_DEBUG
351 static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
353 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
355 uinfo->value.integer.min = 0;
356 uinfo->value.integer.max = 1;
359 static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
361 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
362 hda_nid_t nid = kcontrol->private_value & 0xffff;
363 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
364 long *valp = ucontrol->value.integer.value;
365 unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00);
367 *valp = (val & mask) != 0;
370 static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
373 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
374 hda_nid_t nid = kcontrol->private_value & 0xffff;
375 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
376 long val = *ucontrol->value.integer.value;
377 unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00);
379 /* Set/unset the masked GPIO bit(s) as needed */
380 change = (val==0?0:mask) != (gpio_data & mask);
385 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data);
389 #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
390 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
391 .info = alc_gpio_data_info, \
392 .get = alc_gpio_data_get, \
393 .put = alc_gpio_data_put, \
394 .private_value = nid | (mask<<16) }
395 #endif /* CONFIG_SND_DEBUG */
398 * set up from the preset table
400 static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset)
404 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
405 spec->mixers[spec->num_mixers++] = preset->mixers[i];
406 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++)
407 spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
409 spec->channel_mode = preset->channel_mode;
410 spec->num_channel_mode = preset->num_channel_mode;
412 spec->multiout.max_channels = spec->channel_mode[0].channels;
414 spec->multiout.num_dacs = preset->num_dacs;
415 spec->multiout.dac_nids = preset->dac_nids;
416 spec->multiout.dig_out_nid = preset->dig_out_nid;
417 spec->multiout.hp_nid = preset->hp_nid;
419 spec->input_mux = preset->input_mux;
421 spec->num_adc_nids = preset->num_adc_nids;
422 spec->adc_nids = preset->adc_nids;
423 spec->dig_in_nid = preset->dig_in_nid;
427 * ALC880 3-stack model
429 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
430 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
434 static hda_nid_t alc880_dac_nids[4] = {
435 /* front, rear, clfe, rear_surr */
436 0x02, 0x05, 0x04, 0x03
439 static hda_nid_t alc880_adc_nids[3] = {
444 /* The datasheet says the node 0x07 is connected from inputs,
445 * but it shows zero connection in the real implementation on some devices.
446 * Note: this is a 915GAV bug, fixed on 915GLV
448 static hda_nid_t alc880_adc_nids_alt[2] = {
453 #define ALC880_DIGOUT_NID 0x06
454 #define ALC880_DIGIN_NID 0x0a
456 static struct hda_input_mux alc880_capture_source = {
460 { "Front Mic", 0x3 },
466 /* channel source setting (2/6 channel selection for 3-stack) */
468 static struct hda_verb alc880_threestack_ch2_init[] = {
469 /* set line-in to input, mute it */
470 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
471 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
472 /* set mic-in to input vref 80%, mute it */
473 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
474 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
479 static struct hda_verb alc880_threestack_ch6_init[] = {
480 /* set line-in to output, unmute it */
481 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
482 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
483 /* set mic-in to output, unmute it */
484 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
485 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
489 static struct hda_channel_mode alc880_threestack_modes[2] = {
490 { 2, alc880_threestack_ch2_init },
491 { 6, alc880_threestack_ch6_init },
494 static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
495 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
496 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
497 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
498 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
499 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
500 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
501 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
502 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
503 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
504 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
505 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
506 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
507 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
508 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
509 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
510 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
511 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
512 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
513 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
516 .name = "Channel Mode",
517 .info = alc_ch_mode_info,
518 .get = alc_ch_mode_get,
519 .put = alc_ch_mode_put,
524 /* capture mixer elements */
525 static struct snd_kcontrol_new alc880_capture_mixer[] = {
526 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
527 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
528 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
529 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
530 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
531 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
534 /* The multiple "Capture Source" controls confuse alsamixer
535 * So call somewhat different..
536 * FIXME: the controls appear in the "playback" view!
538 /* .name = "Capture Source", */
539 .name = "Input Source",
541 .info = alc_mux_enum_info,
542 .get = alc_mux_enum_get,
543 .put = alc_mux_enum_put,
548 /* capture mixer elements (in case NID 0x07 not available) */
549 static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
550 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
551 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
552 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
553 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
556 /* The multiple "Capture Source" controls confuse alsamixer
557 * So call somewhat different..
558 * FIXME: the controls appear in the "playback" view!
560 /* .name = "Capture Source", */
561 .name = "Input Source",
563 .info = alc_mux_enum_info,
564 .get = alc_mux_enum_get,
565 .put = alc_mux_enum_put,
573 * ALC880 5-stack model
575 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
576 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
577 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
580 /* additional mixers to alc880_three_stack_mixer */
581 static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
582 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
583 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
587 /* channel source setting (6/8 channel selection for 5-stack) */
589 static struct hda_verb alc880_fivestack_ch6_init[] = {
590 /* set line-in to input, mute it */
591 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
592 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
597 static struct hda_verb alc880_fivestack_ch8_init[] = {
598 /* set line-in to output, unmute it */
599 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
600 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
604 static struct hda_channel_mode alc880_fivestack_modes[2] = {
605 { 6, alc880_fivestack_ch6_init },
606 { 8, alc880_fivestack_ch8_init },
611 * ALC880 6-stack model
613 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
614 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
615 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
618 static hda_nid_t alc880_6st_dac_nids[4] = {
619 /* front, rear, clfe, rear_surr */
620 0x02, 0x03, 0x04, 0x05
623 static struct hda_input_mux alc880_6stack_capture_source = {
627 { "Front Mic", 0x1 },
633 /* fixed 8-channels */
634 static struct hda_channel_mode alc880_sixstack_modes[1] = {
638 static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
639 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
640 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
641 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
642 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
643 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
644 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
645 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
646 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
647 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
648 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
649 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
650 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
651 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
652 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
653 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
654 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
655 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
656 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
657 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
658 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
660 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
661 .name = "Channel Mode",
662 .info = alc_ch_mode_info,
663 .get = alc_ch_mode_get,
664 .put = alc_ch_mode_put,
673 * W810 has rear IO for:
676 * Center/LFE (DAC 04)
679 * The system also has a pair of internal speakers, and a headphone jack.
680 * These are both connected to Line2 on the codec, hence to DAC 02.
682 * There is a variable resistor to control the speaker or headphone
683 * volume. This is a hardware-only device without a software API.
685 * Plugging headphones in will disable the internal speakers. This is
686 * implemented in hardware, not via the driver using jack sense. In
687 * a similar fashion, plugging into the rear socket marked "front" will
688 * disable both the speakers and headphones.
690 * For input, there's a microphone jack, and an "audio in" jack.
691 * These may not do anything useful with this driver yet, because I
692 * haven't setup any initialization verbs for these yet...
695 static hda_nid_t alc880_w810_dac_nids[3] = {
696 /* front, rear/surround, clfe */
700 /* fixed 6 channels */
701 static struct hda_channel_mode alc880_w810_modes[1] = {
705 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
706 static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
707 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
708 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
709 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
710 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
711 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
712 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
713 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
714 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
715 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
723 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
724 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
727 static hda_nid_t alc880_z71v_dac_nids[1] = {
730 #define ALC880_Z71V_HP_DAC 0x03
732 /* fixed 2 channels */
733 static struct hda_channel_mode alc880_2_jack_modes[1] = {
737 static struct snd_kcontrol_new alc880_z71v_mixer[] = {
738 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
739 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
740 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
741 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
742 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
743 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
744 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
745 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
754 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
755 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
758 static hda_nid_t alc880_f1734_dac_nids[1] = {
761 #define ALC880_F1734_HP_DAC 0x02
763 static struct snd_kcontrol_new alc880_f1734_mixer[] = {
764 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
765 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
766 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
767 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
768 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
769 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
770 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
771 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
780 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
781 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
782 * Mic = 0x18, Line = 0x1a
785 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
786 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
788 static struct snd_kcontrol_new alc880_asus_mixer[] = {
789 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
790 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
791 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
792 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
793 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
794 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
795 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
796 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
797 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
798 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
799 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
800 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
801 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
802 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
805 .name = "Channel Mode",
806 .info = alc_ch_mode_info,
807 .get = alc_ch_mode_get,
808 .put = alc_ch_mode_put,
815 * ALC880 ASUS W1V model
817 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
818 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
819 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
822 /* additional mixers to alc880_asus_mixer */
823 static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
824 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
825 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
829 /* additional mixers to alc880_asus_mixer */
830 static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
831 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
832 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
837 static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
838 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
839 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
840 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
841 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
842 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
843 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
844 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
845 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
846 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
848 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
849 /* The multiple "Capture Source" controls confuse alsamixer
850 * So call somewhat different..
851 * FIXME: the controls appear in the "playback" view!
853 /* .name = "Capture Source", */
854 .name = "Input Source",
856 .info = alc_mux_enum_info,
857 .get = alc_mux_enum_get,
858 .put = alc_mux_enum_put,
864 * build control elements
866 static int alc_build_controls(struct hda_codec *codec)
868 struct alc_spec *spec = codec->spec;
872 for (i = 0; i < spec->num_mixers; i++) {
873 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
878 if (spec->multiout.dig_out_nid) {
879 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
883 if (spec->dig_in_nid) {
884 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
893 * initialize the codec volumes, etc
897 * generic initialization of ADC, input mixers and output mixers
899 static struct hda_verb alc880_volume_init_verbs[] = {
901 * Unmute ADC0-2 and set the default input to mic-in
903 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
904 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
905 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
906 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
907 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
908 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
910 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
912 * Note: PASD motherboards uses the Line In 2 as the input for front panel
915 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
916 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
917 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
918 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
919 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
920 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
923 * Set up output mixers (0x0c - 0x0f)
925 /* set vol=0 to output mixers */
926 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
927 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
928 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
929 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
930 /* set up input amps for analog loopback */
931 /* Amp Indices: DAC = 0, mixer = 1 */
932 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
933 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
934 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
935 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
936 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
937 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
938 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
939 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
945 * 3-stack pin configuration:
946 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
948 static struct hda_verb alc880_pin_3stack_init_verbs[] = {
950 * preset connection lists of input pins
951 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
953 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
954 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
955 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
958 * Set pin mode and muting
960 /* set front pin widgets 0x14 for output */
961 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
962 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
963 /* Mic1 (rear panel) pin widget for input and vref at 80% */
964 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
965 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
966 /* Mic2 (as headphone out) for HP output */
967 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
968 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
969 /* Line In pin widget for input */
970 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
971 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
972 /* Line2 (as front mic) pin widget for input and vref at 80% */
973 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
974 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
975 /* CD pin widget for input */
976 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
982 * 5-stack pin configuration:
983 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
984 * line-in/side = 0x1a, f-mic = 0x1b
986 static struct hda_verb alc880_pin_5stack_init_verbs[] = {
988 * preset connection lists of input pins
989 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
991 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
992 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
995 * Set pin mode and muting
997 /* set pin widgets 0x14-0x17 for output */
998 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
999 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1000 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1001 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1002 /* unmute pins for output (no gain on this amp) */
1003 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1004 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1005 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1006 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1008 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1009 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1010 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1011 /* Mic2 (as headphone out) for HP output */
1012 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1013 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1014 /* Line In pin widget for input */
1015 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1016 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1017 /* Line2 (as front mic) pin widget for input and vref at 80% */
1018 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1019 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1020 /* CD pin widget for input */
1021 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1027 * W810 pin configuration:
1028 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
1030 static struct hda_verb alc880_pin_w810_init_verbs[] = {
1031 /* hphone/speaker input selector: front DAC */
1032 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
1034 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1035 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1036 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1037 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1038 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1039 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1041 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1042 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1048 * Z71V pin configuration:
1049 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
1051 static struct hda_verb alc880_pin_z71v_init_verbs[] = {
1052 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1053 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1054 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1055 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1057 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1058 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1059 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1060 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1066 * 6-stack pin configuration:
1067 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
1068 * line = 0x1a, HP = 0x1b
1070 static struct hda_verb alc880_pin_6stack_init_verbs[] = {
1071 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1073 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1074 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1075 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1076 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1077 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1078 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1079 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1080 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1082 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1083 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1084 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1085 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1086 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1087 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1088 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1089 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1090 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1097 * F1734 pin configuration:
1098 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1100 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
1101 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1102 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1103 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1104 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1106 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1107 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1108 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1109 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1111 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1112 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1113 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1114 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1115 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1116 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1117 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1118 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1119 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1126 * ASUS pin configuration:
1127 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1129 static struct hda_verb alc880_pin_asus_init_verbs[] = {
1130 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1131 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1132 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1133 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1135 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1136 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1137 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1138 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1139 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1140 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1141 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1142 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1144 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1145 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1146 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1147 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1148 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1149 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1150 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1151 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1152 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1157 /* Enable GPIO mask and set output */
1158 static struct hda_verb alc880_gpio1_init_verbs[] = {
1159 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1160 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1161 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1166 /* Enable GPIO mask and set output */
1167 static struct hda_verb alc880_gpio2_init_verbs[] = {
1168 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1169 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1170 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1175 /* Clevo m520g init */
1176 static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1177 /* headphone output */
1178 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1180 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1181 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1183 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1184 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1186 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1187 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1188 /* Mic1 (rear panel) */
1189 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1190 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1191 /* Mic2 (front panel) */
1192 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1193 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1195 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1196 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1197 /* change to EAPD mode */
1198 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1199 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
1204 static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1205 /* Headphone output */
1206 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1208 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1209 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1211 /* Line In pin widget for input */
1212 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1213 /* CD pin widget for input */
1214 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1215 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1216 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1218 /* change to EAPD mode */
1219 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1220 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
1228 static int alc_init(struct hda_codec *codec)
1230 struct alc_spec *spec = codec->spec;
1233 for (i = 0; i < spec->num_init_verbs; i++)
1234 snd_hda_sequence_write(codec, spec->init_verbs[i]);
1242 static int alc_resume(struct hda_codec *codec)
1244 struct alc_spec *spec = codec->spec;
1248 for (i = 0; i < spec->num_mixers; i++)
1249 snd_hda_resume_ctls(codec, spec->mixers[i]);
1250 if (spec->multiout.dig_out_nid)
1251 snd_hda_resume_spdif_out(codec);
1252 if (spec->dig_in_nid)
1253 snd_hda_resume_spdif_in(codec);
1260 * Analog playback callbacks
1262 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
1263 struct hda_codec *codec,
1264 struct snd_pcm_substream *substream)
1266 struct alc_spec *spec = codec->spec;
1267 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
1270 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1271 struct hda_codec *codec,
1272 unsigned int stream_tag,
1273 unsigned int format,
1274 struct snd_pcm_substream *substream)
1276 struct alc_spec *spec = codec->spec;
1277 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
1281 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
1282 struct hda_codec *codec,
1283 struct snd_pcm_substream *substream)
1285 struct alc_spec *spec = codec->spec;
1286 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1292 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1293 struct hda_codec *codec,
1294 struct snd_pcm_substream *substream)
1296 struct alc_spec *spec = codec->spec;
1297 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1300 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1301 struct hda_codec *codec,
1302 struct snd_pcm_substream *substream)
1304 struct alc_spec *spec = codec->spec;
1305 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1311 static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1312 struct hda_codec *codec,
1313 unsigned int stream_tag,
1314 unsigned int format,
1315 struct snd_pcm_substream *substream)
1317 struct alc_spec *spec = codec->spec;
1319 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1320 stream_tag, 0, format);
1324 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1325 struct hda_codec *codec,
1326 struct snd_pcm_substream *substream)
1328 struct alc_spec *spec = codec->spec;
1330 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
1337 static struct hda_pcm_stream alc880_pcm_analog_playback = {
1341 /* NID is set in alc_build_pcms */
1343 .open = alc880_playback_pcm_open,
1344 .prepare = alc880_playback_pcm_prepare,
1345 .cleanup = alc880_playback_pcm_cleanup
1349 static struct hda_pcm_stream alc880_pcm_analog_capture = {
1353 /* NID is set in alc_build_pcms */
1355 .prepare = alc880_capture_pcm_prepare,
1356 .cleanup = alc880_capture_pcm_cleanup
1360 static struct hda_pcm_stream alc880_pcm_digital_playback = {
1364 /* NID is set in alc_build_pcms */
1366 .open = alc880_dig_playback_pcm_open,
1367 .close = alc880_dig_playback_pcm_close
1371 static struct hda_pcm_stream alc880_pcm_digital_capture = {
1375 /* NID is set in alc_build_pcms */
1378 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
1379 static struct hda_pcm_stream alc_pcm_null_playback = {
1385 static int alc_build_pcms(struct hda_codec *codec)
1387 struct alc_spec *spec = codec->spec;
1388 struct hda_pcm *info = spec->pcm_rec;
1391 codec->num_pcms = 1;
1392 codec->pcm_info = info;
1394 info->name = spec->stream_name_analog;
1395 if (spec->stream_analog_playback) {
1396 snd_assert(spec->multiout.dac_nids, return -EINVAL);
1397 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1398 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1400 if (spec->stream_analog_capture) {
1401 snd_assert(spec->adc_nids, return -EINVAL);
1402 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1403 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1406 if (spec->channel_mode) {
1407 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1408 for (i = 0; i < spec->num_channel_mode; i++) {
1409 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1410 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1415 /* If the use of more than one ADC is requested for the current
1416 * model, configure a second analog capture-only PCM.
1418 if (spec->num_adc_nids > 1) {
1421 info->name = spec->stream_name_analog;
1422 /* No playback stream for second PCM */
1423 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
1424 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
1425 if (spec->stream_analog_capture) {
1426 snd_assert(spec->adc_nids, return -EINVAL);
1427 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1428 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
1432 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
1435 info->name = spec->stream_name_digital;
1436 if (spec->multiout.dig_out_nid &&
1437 spec->stream_digital_playback) {
1438 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
1439 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
1441 if (spec->dig_in_nid &&
1442 spec->stream_digital_capture) {
1443 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
1444 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
1451 static void alc_free(struct hda_codec *codec)
1453 struct alc_spec *spec = codec->spec;
1459 if (spec->kctl_alloc) {
1460 for (i = 0; i < spec->num_kctl_used; i++)
1461 kfree(spec->kctl_alloc[i].name);
1462 kfree(spec->kctl_alloc);
1469 static struct hda_codec_ops alc_patch_ops = {
1470 .build_controls = alc_build_controls,
1471 .build_pcms = alc_build_pcms,
1475 .resume = alc_resume,
1481 * Test configuration for debugging
1483 * Almost all inputs/outputs are enabled. I/O pins can be configured via
1486 #ifdef CONFIG_SND_DEBUG
1487 static hda_nid_t alc880_test_dac_nids[4] = {
1488 0x02, 0x03, 0x04, 0x05
1491 static struct hda_input_mux alc880_test_capture_source = {
1502 static struct hda_channel_mode alc880_test_modes[4] = {
1509 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1511 static char *texts[] = {
1512 "N/A", "Line Out", "HP Out",
1513 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1515 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1517 uinfo->value.enumerated.items = 8;
1518 if (uinfo->value.enumerated.item >= 8)
1519 uinfo->value.enumerated.item = 7;
1520 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1524 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1526 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1527 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1528 unsigned int pin_ctl, item = 0;
1530 pin_ctl = snd_hda_codec_read(codec, nid, 0,
1531 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1532 if (pin_ctl & AC_PINCTL_OUT_EN) {
1533 if (pin_ctl & AC_PINCTL_HP_EN)
1537 } else if (pin_ctl & AC_PINCTL_IN_EN) {
1538 switch (pin_ctl & AC_PINCTL_VREFEN) {
1539 case AC_PINCTL_VREF_HIZ: item = 3; break;
1540 case AC_PINCTL_VREF_50: item = 4; break;
1541 case AC_PINCTL_VREF_GRD: item = 5; break;
1542 case AC_PINCTL_VREF_80: item = 6; break;
1543 case AC_PINCTL_VREF_100: item = 7; break;
1546 ucontrol->value.enumerated.item[0] = item;
1550 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1552 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1553 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1554 static unsigned int ctls[] = {
1555 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
1556 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
1557 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
1558 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
1559 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
1560 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
1562 unsigned int old_ctl, new_ctl;
1564 old_ctl = snd_hda_codec_read(codec, nid, 0,
1565 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1566 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
1567 if (old_ctl != new_ctl) {
1568 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
1569 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1570 ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
1576 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1578 static char *texts[] = {
1579 "Front", "Surround", "CLFE", "Side"
1581 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1583 uinfo->value.enumerated.items = 4;
1584 if (uinfo->value.enumerated.item >= 4)
1585 uinfo->value.enumerated.item = 3;
1586 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1590 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1592 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1593 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1596 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
1597 ucontrol->value.enumerated.item[0] = sel & 3;
1601 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1603 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1604 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1607 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
1608 if (ucontrol->value.enumerated.item[0] != sel) {
1609 sel = ucontrol->value.enumerated.item[0] & 3;
1610 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
1616 #define PIN_CTL_TEST(xname,nid) { \
1617 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1619 .info = alc_test_pin_ctl_info, \
1620 .get = alc_test_pin_ctl_get, \
1621 .put = alc_test_pin_ctl_put, \
1622 .private_value = nid \
1625 #define PIN_SRC_TEST(xname,nid) { \
1626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1628 .info = alc_test_pin_src_info, \
1629 .get = alc_test_pin_src_get, \
1630 .put = alc_test_pin_src_put, \
1631 .private_value = nid \
1634 static struct snd_kcontrol_new alc880_test_mixer[] = {
1635 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1636 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1637 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
1638 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1639 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1640 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1641 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
1642 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1643 PIN_CTL_TEST("Front Pin Mode", 0x14),
1644 PIN_CTL_TEST("Surround Pin Mode", 0x15),
1645 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1646 PIN_CTL_TEST("Side Pin Mode", 0x17),
1647 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1648 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1649 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1650 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1651 PIN_SRC_TEST("In-1 Pin Source", 0x18),
1652 PIN_SRC_TEST("In-2 Pin Source", 0x19),
1653 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1654 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1655 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
1656 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
1657 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
1658 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
1659 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
1660 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
1661 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
1662 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
1663 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
1664 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
1666 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1667 .name = "Channel Mode",
1668 .info = alc_ch_mode_info,
1669 .get = alc_ch_mode_get,
1670 .put = alc_ch_mode_put,
1675 static struct hda_verb alc880_test_init_verbs[] = {
1676 /* Unmute inputs of 0x0c - 0x0f */
1677 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1678 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1679 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1680 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1681 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1682 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1683 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1684 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1685 /* Vol output for 0x0c-0x0f */
1686 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1687 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1688 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1689 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1690 /* Set output pins 0x14-0x17 */
1691 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1692 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1693 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1694 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1695 /* Unmute output pins 0x14-0x17 */
1696 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1697 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1698 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1699 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1700 /* Set input pins 0x18-0x1c */
1701 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1702 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1703 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1704 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1705 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1706 /* Mute input pins 0x18-0x1b */
1707 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1708 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1709 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1710 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1712 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1713 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1714 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1715 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1716 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1717 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1718 /* Analog input/passthru */
1719 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1720 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1721 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1722 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1723 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1731 static struct hda_board_config alc880_cfg_tbl[] = {
1732 /* Back 3 jack, front 2 jack */
1733 { .modelname = "3stack", .config = ALC880_3ST },
1734 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
1735 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
1736 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
1737 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
1738 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
1739 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
1740 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
1741 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
1742 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
1743 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
1744 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
1745 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
1746 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
1747 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
1748 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
1749 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
1750 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
1751 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
1752 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
1753 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
1754 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
1755 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
1756 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
1757 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
1758 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
1759 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
1760 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
1761 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
1762 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
1763 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1764 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1765 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1767 { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
1769 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1770 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
1771 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
1772 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
1774 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1775 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1776 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1777 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1778 /* Clevo m520G NB */
1779 { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO },
1781 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1782 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
1783 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
1784 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
1786 /* Back 5 jack, front 2 jack */
1787 { .modelname = "5stack", .config = ALC880_5ST },
1788 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
1789 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
1790 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
1791 { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
1792 { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
1794 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1795 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1796 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
1797 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
1798 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
1799 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
1800 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
1801 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
1802 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
1803 { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
1804 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
1805 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1806 { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
1807 /* note subvendor = 0 below */
1808 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1810 { .modelname = "w810", .config = ALC880_W810 },
1811 { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
1813 { .modelname = "z71v", .config = ALC880_Z71V },
1814 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1816 { .modelname = "6stack", .config = ALC880_6ST },
1817 { .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
1818 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
1819 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1820 { .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
1822 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
1823 { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
1824 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1825 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1826 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1827 { .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
1828 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
1829 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
1830 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
1831 { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
1833 { .modelname = "asus", .config = ALC880_ASUS },
1834 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
1835 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
1836 { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
1837 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
1838 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
1839 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
1840 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
1841 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
1842 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1843 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1844 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1845 { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
1847 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1848 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
1850 { .modelname = "F1734", .config = ALC880_F1734 },
1851 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1852 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
1854 #ifdef CONFIG_SND_DEBUG
1855 { .modelname = "test", .config = ALC880_TEST },
1857 { .modelname = "auto", .config = ALC880_AUTO },
1863 * ALC880 codec presets
1865 static struct alc_config_preset alc880_presets[] = {
1867 .mixers = { alc880_three_stack_mixer },
1868 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1869 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1870 .dac_nids = alc880_dac_nids,
1871 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1872 .channel_mode = alc880_threestack_modes,
1873 .input_mux = &alc880_capture_source,
1875 [ALC880_3ST_DIG] = {
1876 .mixers = { alc880_three_stack_mixer },
1877 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1878 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1879 .dac_nids = alc880_dac_nids,
1880 .dig_out_nid = ALC880_DIGOUT_NID,
1881 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1882 .channel_mode = alc880_threestack_modes,
1883 .input_mux = &alc880_capture_source,
1885 [ALC880_TCL_S700] = {
1886 .mixers = { alc880_tcl_s700_mixer },
1887 .init_verbs = { alc880_volume_init_verbs,
1888 alc880_pin_tcl_S700_init_verbs,
1889 alc880_gpio2_init_verbs },
1890 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1891 .dac_nids = alc880_dac_nids,
1893 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1894 .channel_mode = alc880_2_jack_modes,
1895 .input_mux = &alc880_capture_source,
1898 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1899 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1900 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1901 .dac_nids = alc880_dac_nids,
1902 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1903 .channel_mode = alc880_fivestack_modes,
1904 .input_mux = &alc880_capture_source,
1906 [ALC880_5ST_DIG] = {
1907 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
1908 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1909 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1910 .dac_nids = alc880_dac_nids,
1911 .dig_out_nid = ALC880_DIGOUT_NID,
1912 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1913 .channel_mode = alc880_fivestack_modes,
1914 .input_mux = &alc880_capture_source,
1917 .mixers = { alc880_six_stack_mixer },
1918 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1919 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1920 .dac_nids = alc880_6st_dac_nids,
1921 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1922 .channel_mode = alc880_sixstack_modes,
1923 .input_mux = &alc880_6stack_capture_source,
1925 [ALC880_6ST_DIG] = {
1926 .mixers = { alc880_six_stack_mixer },
1927 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1928 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1929 .dac_nids = alc880_6st_dac_nids,
1930 .dig_out_nid = ALC880_DIGOUT_NID,
1931 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1932 .channel_mode = alc880_sixstack_modes,
1933 .input_mux = &alc880_6stack_capture_source,
1936 .mixers = { alc880_w810_base_mixer },
1937 .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
1938 alc880_gpio2_init_verbs },
1939 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
1940 .dac_nids = alc880_w810_dac_nids,
1941 .dig_out_nid = ALC880_DIGOUT_NID,
1942 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
1943 .channel_mode = alc880_w810_modes,
1944 .input_mux = &alc880_capture_source,
1947 .mixers = { alc880_z71v_mixer },
1948 .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
1949 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
1950 .dac_nids = alc880_z71v_dac_nids,
1951 .dig_out_nid = ALC880_DIGOUT_NID,
1953 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1954 .channel_mode = alc880_2_jack_modes,
1955 .input_mux = &alc880_capture_source,
1958 .mixers = { alc880_f1734_mixer },
1959 .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
1960 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
1961 .dac_nids = alc880_f1734_dac_nids,
1963 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1964 .channel_mode = alc880_2_jack_modes,
1965 .input_mux = &alc880_capture_source,
1968 .mixers = { alc880_asus_mixer },
1969 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1970 alc880_gpio1_init_verbs },
1971 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1972 .dac_nids = alc880_asus_dac_nids,
1973 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1974 .channel_mode = alc880_asus_modes,
1975 .input_mux = &alc880_capture_source,
1977 [ALC880_ASUS_DIG] = {
1978 .mixers = { alc880_asus_mixer },
1979 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1980 alc880_gpio1_init_verbs },
1981 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1982 .dac_nids = alc880_asus_dac_nids,
1983 .dig_out_nid = ALC880_DIGOUT_NID,
1984 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1985 .channel_mode = alc880_asus_modes,
1986 .input_mux = &alc880_capture_source,
1988 [ALC880_ASUS_DIG2] = {
1989 .mixers = { alc880_asus_mixer },
1990 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1991 alc880_gpio2_init_verbs }, /* use GPIO2 */
1992 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1993 .dac_nids = alc880_asus_dac_nids,
1994 .dig_out_nid = ALC880_DIGOUT_NID,
1995 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1996 .channel_mode = alc880_asus_modes,
1997 .input_mux = &alc880_capture_source,
1999 [ALC880_ASUS_W1V] = {
2000 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
2001 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
2002 alc880_gpio1_init_verbs },
2003 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2004 .dac_nids = alc880_asus_dac_nids,
2005 .dig_out_nid = ALC880_DIGOUT_NID,
2006 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2007 .channel_mode = alc880_asus_modes,
2008 .input_mux = &alc880_capture_source,
2010 [ALC880_UNIWILL_DIG] = {
2011 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
2012 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
2013 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2014 .dac_nids = alc880_asus_dac_nids,
2015 .dig_out_nid = ALC880_DIGOUT_NID,
2016 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
2017 .channel_mode = alc880_asus_modes,
2018 .input_mux = &alc880_capture_source,
2021 .mixers = { alc880_three_stack_mixer },
2022 .init_verbs = { alc880_volume_init_verbs,
2023 alc880_pin_clevo_init_verbs },
2024 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
2025 .dac_nids = alc880_dac_nids,
2027 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2028 .channel_mode = alc880_threestack_modes,
2029 .input_mux = &alc880_capture_source,
2031 #ifdef CONFIG_SND_DEBUG
2033 .mixers = { alc880_test_mixer },
2034 .init_verbs = { alc880_test_init_verbs },
2035 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
2036 .dac_nids = alc880_test_dac_nids,
2037 .dig_out_nid = ALC880_DIGOUT_NID,
2038 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
2039 .channel_mode = alc880_test_modes,
2040 .input_mux = &alc880_test_capture_source,
2046 * Automatic parse of I/O pins from the BIOS configuration
2049 #define NUM_CONTROL_ALLOC 32
2050 #define NUM_VERB_ALLOC 32
2054 ALC_CTL_WIDGET_MUTE,
2057 static struct snd_kcontrol_new alc880_control_templates[] = {
2058 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2059 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2060 HDA_BIND_MUTE(NULL, 0, 0, 0),
2063 /* add dynamic controls */
2064 static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
2066 struct snd_kcontrol_new *knew;
2068 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
2069 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
2071 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
2074 if (spec->kctl_alloc) {
2075 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2076 kfree(spec->kctl_alloc);
2078 spec->kctl_alloc = knew;
2079 spec->num_kctl_alloc = num;
2082 knew = &spec->kctl_alloc[spec->num_kctl_used];
2083 *knew = alc880_control_templates[type];
2084 knew->name = kstrdup(name, GFP_KERNEL);
2087 knew->private_value = val;
2088 spec->num_kctl_used++;
2092 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
2093 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
2094 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
2095 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
2096 #define alc880_is_input_pin(nid) ((nid) >= 0x18)
2097 #define alc880_input_pin_idx(nid) ((nid) - 0x18)
2098 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
2099 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
2100 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
2101 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
2102 #define ALC880_PIN_CD_NID 0x1c
2104 /* fill in the dac_nids table from the parsed pin configuration */
2105 static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
2111 memset(assigned, 0, sizeof(assigned));
2112 spec->multiout.dac_nids = spec->private_dac_nids;
2114 /* check the pins hardwired to audio widget */
2115 for (i = 0; i < cfg->line_outs; i++) {
2116 nid = cfg->line_out_pins[i];
2117 if (alc880_is_fixed_pin(nid)) {
2118 int idx = alc880_fixed_pin_idx(nid);
2119 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
2123 /* left pins can be connect to any audio widget */
2124 for (i = 0; i < cfg->line_outs; i++) {
2125 nid = cfg->line_out_pins[i];
2126 if (alc880_is_fixed_pin(nid))
2128 /* search for an empty channel */
2129 for (j = 0; j < cfg->line_outs; j++) {
2130 if (! assigned[j]) {
2131 spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
2137 spec->multiout.num_dacs = cfg->line_outs;
2141 /* add playback controls from the parsed DAC table */
2142 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
2143 const struct auto_pin_cfg *cfg)
2146 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2150 for (i = 0; i < cfg->line_outs; i++) {
2151 if (! spec->multiout.dac_nids[i])
2153 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
2156 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
2157 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
2159 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
2160 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
2162 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
2163 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
2165 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
2166 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
2169 sprintf(name, "%s Playback Volume", chname[i]);
2170 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2171 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2173 sprintf(name, "%s Playback Switch", chname[i]);
2174 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2175 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2182 /* add playback controls for speaker and HP outputs */
2183 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
2193 if (alc880_is_fixed_pin(pin)) {
2194 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
2195 if (! spec->multiout.dac_nids[0]) {
2196 /* use this as the primary output */
2197 spec->multiout.dac_nids[0] = nid;
2198 if (! spec->multiout.num_dacs)
2199 spec->multiout.num_dacs = 1;
2201 /* specify the DAC as the extra output */
2202 spec->multiout.hp_nid = nid;
2203 /* control HP volume/switch on the output mixer amp */
2204 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
2205 sprintf(name, "%s Playback Volume", pfx);
2206 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2207 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2209 sprintf(name, "%s Playback Switch", pfx);
2210 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2211 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2213 } else if (alc880_is_multi_pin(pin)) {
2214 /* set manual connection */
2215 if (! spec->multiout.dac_nids[0]) {
2216 /* use this as the primary output */
2217 spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
2218 if (! spec->multiout.num_dacs)
2219 spec->multiout.num_dacs = 1;
2221 /* we have only a switch on HP-out PIN */
2222 sprintf(name, "%s Playback Switch", pfx);
2223 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2224 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
2230 /* create input playback/capture controls for the given pin */
2231 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
2232 int idx, hda_nid_t mix_nid)
2237 sprintf(name, "%s Playback Volume", ctlname);
2238 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2239 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2241 sprintf(name, "%s Playback Switch", ctlname);
2242 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2243 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2248 /* create playback/capture controls for input pins */
2249 static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
2250 const struct auto_pin_cfg *cfg)
2252 struct hda_input_mux *imux = &spec->private_imux;
2255 for (i = 0; i < AUTO_PIN_LAST; i++) {
2256 if (alc880_is_input_pin(cfg->input_pins[i])) {
2257 idx = alc880_input_pin_idx(cfg->input_pins[i]);
2258 err = new_analog_input(spec, cfg->input_pins[i],
2259 auto_pin_cfg_labels[i],
2263 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2264 imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
2271 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
2272 hda_nid_t nid, int pin_type,
2276 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2277 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2278 /* need the manual connection? */
2279 if (alc880_is_multi_pin(nid)) {
2280 struct alc_spec *spec = codec->spec;
2281 int idx = alc880_multi_pin_idx(nid);
2282 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
2283 AC_VERB_SET_CONNECT_SEL,
2284 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
2288 static void alc880_auto_init_multi_out(struct hda_codec *codec)
2290 struct alc_spec *spec = codec->spec;
2293 for (i = 0; i < spec->autocfg.line_outs; i++) {
2294 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2295 alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2299 static void alc880_auto_init_extra_out(struct hda_codec *codec)
2301 struct alc_spec *spec = codec->spec;
2304 pin = spec->autocfg.speaker_pin;
2305 if (pin) /* connect to front */
2306 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2307 pin = spec->autocfg.hp_pin;
2308 if (pin) /* connect to front */
2309 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2312 static void alc880_auto_init_analog_input(struct hda_codec *codec)
2314 struct alc_spec *spec = codec->spec;
2317 for (i = 0; i < AUTO_PIN_LAST; i++) {
2318 hda_nid_t nid = spec->autocfg.input_pins[i];
2319 if (alc880_is_input_pin(nid)) {
2320 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2321 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2322 if (nid != ALC880_PIN_CD_NID)
2323 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2329 /* parse the BIOS configuration and set up the alc_spec */
2330 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2331 static int alc880_parse_auto_config(struct hda_codec *codec)
2333 struct alc_spec *spec = codec->spec;
2335 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
2337 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2338 alc880_ignore)) < 0)
2340 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
2341 ! spec->autocfg.hp_pin)
2342 return 0; /* can't find valid BIOS pin config */
2344 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
2345 (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2346 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2348 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2349 "Headphone")) < 0 ||
2350 (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2353 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2355 if (spec->autocfg.dig_out_pin)
2356 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2357 if (spec->autocfg.dig_in_pin)
2358 spec->dig_in_nid = ALC880_DIGIN_NID;
2360 if (spec->kctl_alloc)
2361 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2363 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2365 spec->input_mux = &spec->private_imux;
2370 /* init callback for auto-configuration model -- overriding the default init */
2371 static int alc880_auto_init(struct hda_codec *codec)
2374 alc880_auto_init_multi_out(codec);
2375 alc880_auto_init_extra_out(codec);
2376 alc880_auto_init_analog_input(codec);
2381 * OK, here we have finally the patch for ALC880
2384 static int patch_alc880(struct hda_codec *codec)
2386 struct alc_spec *spec;
2390 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2396 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
2397 if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
2398 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2399 board_config = ALC880_AUTO;
2402 if (board_config == ALC880_AUTO) {
2403 /* automatic parse from the BIOS config */
2404 err = alc880_parse_auto_config(codec);
2409 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
2410 board_config = ALC880_3ST;
2414 if (board_config != ALC880_AUTO)
2415 setup_preset(spec, &alc880_presets[board_config]);
2417 spec->stream_name_analog = "ALC880 Analog";
2418 spec->stream_analog_playback = &alc880_pcm_analog_playback;
2419 spec->stream_analog_capture = &alc880_pcm_analog_capture;
2421 spec->stream_name_digital = "ALC880 Digital";
2422 spec->stream_digital_playback = &alc880_pcm_digital_playback;
2423 spec->stream_digital_capture = &alc880_pcm_digital_capture;
2425 if (! spec->adc_nids && spec->input_mux) {
2426 /* check whether NID 0x07 is valid */
2427 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
2428 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2429 if (wcap != AC_WID_AUD_IN) {
2430 spec->adc_nids = alc880_adc_nids_alt;
2431 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
2432 spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
2435 spec->adc_nids = alc880_adc_nids;
2436 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
2437 spec->mixers[spec->num_mixers] = alc880_capture_mixer;
2442 codec->patch_ops = alc_patch_ops;
2443 if (board_config == ALC880_AUTO)
2444 codec->patch_ops.init = alc880_auto_init;
2454 static hda_nid_t alc260_dac_nids[1] = {
2459 static hda_nid_t alc260_adc_nids[1] = {
2464 static hda_nid_t alc260_adc_nids_alt[1] = {
2469 static hda_nid_t alc260_hp_adc_nids[2] = {
2474 /* NIDs used when simultaneous access to both ADCs makes sense. Note that
2475 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
2477 static hda_nid_t alc260_dual_adc_nids[2] = {
2482 #define ALC260_DIGOUT_NID 0x03
2483 #define ALC260_DIGIN_NID 0x06
2485 static struct hda_input_mux alc260_capture_source = {
2489 { "Front Mic", 0x1 },
2495 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
2496 * headphone jack and the internal CD lines.
2498 static struct hda_input_mux alc260_fujitsu_capture_source = {
2501 { "Mic/Line", 0x0 },
2503 { "Headphone", 0x2 },
2508 * This is just place-holder, so there's something for alc_build_pcms to look
2509 * at when it calculates the maximum number of channels. ALC260 has no mixer
2510 * element which allows changing the channel mode, so the verb list is
2513 static struct hda_channel_mode alc260_modes[1] = {
2518 /* Mixer combinations
2520 * basic: base_output + input + pc_beep + capture
2521 * HP: base_output + input + capture_alt
2522 * HP_3013: hp_3013 + input + capture
2523 * fujitsu: fujitsu + capture
2526 static struct snd_kcontrol_new alc260_base_output_mixer[] = {
2527 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2528 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2529 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2530 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2531 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2532 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2536 static struct snd_kcontrol_new alc260_input_mixer[] = {
2537 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2538 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2539 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2540 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2541 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2542 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2543 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2544 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2548 static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
2549 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2550 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2554 static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
2555 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2556 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2557 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
2558 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
2559 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2560 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
2561 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2562 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
2566 static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2567 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2568 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
2569 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
2570 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2571 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2572 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
2573 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
2574 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
2575 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2576 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2577 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2578 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2582 /* capture mixer elements */
2583 static struct snd_kcontrol_new alc260_capture_mixer[] = {
2584 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2585 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2586 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
2587 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
2589 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2590 /* The multiple "Capture Source" controls confuse alsamixer
2591 * So call somewhat different..
2592 * FIXME: the controls appear in the "playback" view!
2594 /* .name = "Capture Source", */
2595 .name = "Input Source",
2597 .info = alc_mux_enum_info,
2598 .get = alc_mux_enum_get,
2599 .put = alc_mux_enum_put,
2604 static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
2605 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2606 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2608 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2609 /* The multiple "Capture Source" controls confuse alsamixer
2610 * So call somewhat different..
2611 * FIXME: the controls appear in the "playback" view!
2613 /* .name = "Capture Source", */
2614 .name = "Input Source",
2616 .info = alc_mux_enum_info,
2617 .get = alc_mux_enum_get,
2618 .put = alc_mux_enum_put,
2624 * initialization verbs
2626 static struct hda_verb alc260_init_verbs[] = {
2627 /* Line In pin widget for input */
2628 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2629 /* CD pin widget for input */
2630 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2631 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2632 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2633 /* Mic2 (front panel) pin widget for input and vref at 80% */
2634 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2635 /* LINE-2 is used for line-out in rear */
2636 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2637 /* select line-out */
2638 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
2640 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2642 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2644 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2645 /* mute capture amp left and right */
2646 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2647 /* set connection select to line in (default select for this ADC) */
2648 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2649 /* mute capture amp left and right */
2650 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2651 /* set connection select to line in (default select for this ADC) */
2652 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
2653 /* set vol=0 Line-Out mixer amp left and right */
2654 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2655 /* unmute pin widget amp left and right (no gain on this amp) */
2656 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2657 /* set vol=0 HP mixer amp left and right */
2658 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2659 /* unmute pin widget amp left and right (no gain on this amp) */
2660 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2661 /* set vol=0 Mono mixer amp left and right */
2662 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2663 /* unmute pin widget amp left and right (no gain on this amp) */
2664 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2665 /* unmute LINE-2 out pin */
2666 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2667 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2669 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2671 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2673 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2674 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2675 /* mute Front out path */
2676 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2677 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2678 /* mute Headphone out path */
2679 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2680 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2681 /* mute Mono out path */
2682 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2683 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2687 static struct hda_verb alc260_hp_init_verbs[] = {
2688 /* Headphone and output */
2689 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2691 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2692 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2693 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2694 /* Mic2 (front panel) pin widget for input and vref at 80% */
2695 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2696 /* Line In pin widget for input */
2697 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2698 /* Line-2 pin widget for output */
2699 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2700 /* CD pin widget for input */
2701 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2702 /* unmute amp left and right */
2703 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2704 /* set connection select to line in (default select for this ADC) */
2705 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2706 /* unmute Line-Out mixer amp left and right (volume = 0) */
2707 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2708 /* mute pin widget amp left and right (no gain on this amp) */
2709 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2710 /* unmute HP mixer amp left and right (volume = 0) */
2711 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2712 /* mute pin widget amp left and right (no gain on this amp) */
2713 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2714 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2716 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2717 /* unmute Line In */
2718 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2720 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2721 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2722 /* Unmute Front out path */
2723 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2724 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2725 /* Unmute Headphone out path */
2726 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2727 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2728 /* Unmute Mono out path */
2729 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2730 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2734 static struct hda_verb alc260_hp_3013_init_verbs[] = {
2735 /* Line out and output */
2736 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2738 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2739 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2740 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2741 /* Mic2 (front panel) pin widget for input and vref at 80% */
2742 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2743 /* Line In pin widget for input */
2744 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2745 /* Headphone pin widget for output */
2746 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2747 /* CD pin widget for input */
2748 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2749 /* unmute amp left and right */
2750 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2751 /* set connection select to line in (default select for this ADC) */
2752 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2753 /* unmute Line-Out mixer amp left and right (volume = 0) */
2754 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2755 /* mute pin widget amp left and right (no gain on this amp) */
2756 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2757 /* unmute HP mixer amp left and right (volume = 0) */
2758 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2759 /* mute pin widget amp left and right (no gain on this amp) */
2760 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2761 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2763 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2764 /* unmute Line In */
2765 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2767 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2768 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2769 /* Unmute Front out path */
2770 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2771 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2772 /* Unmute Headphone out path */
2773 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2774 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2775 /* Unmute Mono out path */
2776 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2777 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2781 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2784 static struct hda_verb alc260_fujitsu_init_verbs[] = {
2785 /* Disable all GPIOs */
2786 {0x01, AC_VERB_SET_GPIO_MASK, 0},
2787 /* Internal speaker is connected to headphone pin */
2788 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2789 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
2790 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2791 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2792 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2793 /* Ensure all other unused pins are disabled and muted.
2794 * Note: trying to set widget 0x15 to anything blocks all audio
2795 * output for some reason, so just leave that at the default.
2797 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2798 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2799 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2800 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2801 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2802 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2803 /* Disable digital (SPDIF) pins */
2804 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2805 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2807 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
2808 * when acting as an output.
2810 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2812 /* Start with output sum widgets muted and their output gains at min */
2813 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2814 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2815 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2816 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2817 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2818 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2819 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2820 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2821 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2823 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2824 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2825 /* Unmute Line1 pin widget output buffer since it starts as an output.
2826 * If the pin mode is changed by the user the pin mode control will
2827 * take care of enabling the pin's input/output buffers as needed.
2828 * Therefore there's no need to enable the input buffer at this
2831 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2832 /* Unmute input buffer of pin widget used for Line-in (no equiv
2835 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2837 /* Mute capture amp left and right */
2838 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2839 /* Set ADC connection select to match default mixer setting - line
2842 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2844 /* Do the same for the second ADC: mute capture input amp and
2845 * set ADC connection to line in
2847 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2848 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2850 /* Mute all inputs to mixer widget (even unconnected ones) */
2851 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2852 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2853 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2854 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2855 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2856 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2857 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2858 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2863 /* Test configuration for debugging, modelled after the ALC880 test
2866 #ifdef CONFIG_SND_DEBUG
2867 static hda_nid_t alc260_test_dac_nids[1] = {
2870 static hda_nid_t alc260_test_adc_nids[2] = {
2873 /* This is a bit messy since the two input muxes in the ALC260 have slight
2874 * variations in their signal assignments. The ideal way to deal with this
2875 * is to extend alc_spec.input_mux to allow a different input MUX for each
2876 * ADC. For the purposes of the test model it's sufficient to just list
2877 * both options for affected signal indices. The separate input mux
2878 * functionality only needs to be considered if a model comes along which
2879 * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
2882 static struct hda_input_mux alc260_test_capture_source = {
2885 { "MIC1 pin", 0x0 },
2886 { "MIC2 pin", 0x1 },
2887 { "LINE1 pin", 0x2 },
2888 { "LINE2 pin", 0x3 },
2890 { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
2891 { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
2892 { "HP-OUT pin (cap2 only)", 0x7 },
2895 static struct snd_kcontrol_new alc260_test_mixer[] = {
2896 /* Output driver widgets */
2897 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2898 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2899 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2900 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
2901 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2902 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
2904 /* Modes for retasking pin widgets */
2905 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
2906 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
2907 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
2908 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
2909 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
2910 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
2912 /* Loopback mixer controls */
2913 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
2914 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
2915 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
2916 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
2917 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
2918 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
2919 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
2920 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
2921 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2922 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2923 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2924 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2925 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
2926 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
2927 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
2928 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
2930 /* Controls for GPIO pins, assuming they are configured as outputs */
2931 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
2932 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
2933 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
2934 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
2938 static struct hda_verb alc260_test_init_verbs[] = {
2939 /* Enable all GPIOs as outputs with an initial value of 0 */
2940 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
2941 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
2942 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
2944 /* Enable retasking pins as output, initially without power amp */
2945 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2946 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2947 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2948 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2949 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2950 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2952 /* Disable digital (SPDIF) pins for now */
2953 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2954 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2956 /* Ensure mic1, mic2, line1 and line2 pin widget take input from the
2957 * OUT1 sum bus when acting as an output.
2959 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
2960 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
2961 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2962 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
2964 /* Start with output sum widgets muted and their output gains at min */
2965 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2966 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2967 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2968 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2969 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2970 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2971 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2972 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2973 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2975 /* Unmute retasking pin widget output buffers since the default
2976 * state appears to be output. As the pin mode is changed by the
2977 * user the pin mode control will take care of enabling the pin's
2978 * input/output buffers as needed.
2980 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2981 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2982 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2983 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2984 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2985 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2986 /* Also unmute the mono-out pin widget */
2987 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2989 /* Mute capture amp left and right */
2990 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2991 /* Set ADC connection select to match default mixer setting - line
2994 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2996 /* Do the same for the second ADC: mute capture input amp and
2997 * set ADC connection to line in
2999 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3000 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3002 /* Mute all inputs to mixer widget (even unconnected ones) */
3003 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
3004 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
3005 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
3006 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
3007 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
3008 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
3009 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
3010 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
3016 static struct hda_pcm_stream alc260_pcm_analog_playback = {
3022 static struct hda_pcm_stream alc260_pcm_analog_capture = {
3028 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
3029 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
3032 * for BIOS auto-configuration
3035 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
3039 unsigned long vol_val, sw_val;
3043 if (nid >= 0x0f && nid < 0x11) {
3044 nid_vol = nid - 0x7;
3045 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
3046 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3047 } else if (nid == 0x11) {
3048 nid_vol = nid - 0x7;
3049 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
3050 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
3051 } else if (nid >= 0x12 && nid <= 0x15) {
3053 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
3054 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3058 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
3059 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
3061 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
3062 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
3067 /* add playback controls from the parsed DAC table */
3068 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
3069 const struct auto_pin_cfg *cfg)
3074 spec->multiout.num_dacs = 1;
3075 spec->multiout.dac_nids = spec->private_dac_nids;
3076 spec->multiout.dac_nids[0] = 0x02;
3078 nid = cfg->line_out_pins[0];
3080 err = alc260_add_playback_controls(spec, nid, "Front");
3085 nid = cfg->speaker_pin;
3087 err = alc260_add_playback_controls(spec, nid, "Speaker");
3094 err = alc260_add_playback_controls(spec, nid, "Headphone");
3101 /* create playback/capture controls for input pins */
3102 static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
3103 const struct auto_pin_cfg *cfg)
3105 struct hda_input_mux *imux = &spec->private_imux;
3108 for (i = 0; i < AUTO_PIN_LAST; i++) {
3109 if (cfg->input_pins[i] >= 0x12) {
3110 idx = cfg->input_pins[i] - 0x12;
3111 err = new_analog_input(spec, cfg->input_pins[i],
3112 auto_pin_cfg_labels[i], idx, 0x07);
3115 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3116 imux->items[imux->num_items].index = idx;
3119 if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
3120 idx = cfg->input_pins[i] - 0x09;
3121 err = new_analog_input(spec, cfg->input_pins[i],
3122 auto_pin_cfg_labels[i], idx, 0x07);
3125 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3126 imux->items[imux->num_items].index = idx;
3133 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3134 hda_nid_t nid, int pin_type,
3138 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3139 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3140 /* need the manual connection? */
3142 int idx = nid - 0x12;
3143 snd_hda_codec_write(codec, idx + 0x0b, 0,
3144 AC_VERB_SET_CONNECT_SEL, sel_idx);
3149 static void alc260_auto_init_multi_out(struct hda_codec *codec)
3151 struct alc_spec *spec = codec->spec;
3154 nid = spec->autocfg.line_out_pins[0];
3156 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3158 nid = spec->autocfg.speaker_pin;
3160 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3162 nid = spec->autocfg.hp_pin;
3164 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3167 #define ALC260_PIN_CD_NID 0x16
3168 static void alc260_auto_init_analog_input(struct hda_codec *codec)
3170 struct alc_spec *spec = codec->spec;
3173 for (i = 0; i < AUTO_PIN_LAST; i++) {
3174 hda_nid_t nid = spec->autocfg.input_pins[i];
3176 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3177 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3178 if (nid != ALC260_PIN_CD_NID)
3179 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3186 * generic initialization of ADC, input mixers and output mixers
3188 static struct hda_verb alc260_volume_init_verbs[] = {
3190 * Unmute ADC0-1 and set the default input to mic-in
3192 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3193 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3194 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3195 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3197 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3199 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3202 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3203 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3204 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3205 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3206 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3207 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3210 * Set up output mixers (0x08 - 0x0a)
3212 /* set vol=0 to output mixers */
3213 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3214 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3215 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3216 /* set up input amps for analog loopback */
3217 /* Amp Indices: DAC = 0, mixer = 1 */
3218 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3219 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3220 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3221 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3222 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3223 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3228 static int alc260_parse_auto_config(struct hda_codec *codec)
3230 struct alc_spec *spec = codec->spec;
3233 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
3235 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3236 alc260_ignore)) < 0)
3238 if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
3240 if (! spec->kctl_alloc)
3241 return 0; /* can't find valid BIOS pin config */
3242 if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3245 spec->multiout.max_channels = 2;
3247 if (spec->autocfg.dig_out_pin)
3248 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
3249 if (spec->kctl_alloc)
3250 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3252 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
3254 spec->input_mux = &spec->private_imux;
3256 /* check whether NID 0x04 is valid */
3257 wcap = get_wcaps(codec, 0x04);
3258 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3259 if (wcap != AC_WID_AUD_IN) {
3260 spec->adc_nids = alc260_adc_nids_alt;
3261 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
3262 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
3264 spec->adc_nids = alc260_adc_nids;
3265 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
3266 spec->mixers[spec->num_mixers] = alc260_capture_mixer;
3273 /* init callback for auto-configuration model -- overriding the default init */
3274 static int alc260_auto_init(struct hda_codec *codec)
3277 alc260_auto_init_multi_out(codec);
3278 alc260_auto_init_analog_input(codec);
3283 * ALC260 configurations
3285 static struct hda_board_config alc260_cfg_tbl[] = {
3286 { .modelname = "basic", .config = ALC260_BASIC },
3287 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
3288 .config = ALC260_BASIC }, /* Sony VAIO */
3289 { .modelname = "hp", .config = ALC260_HP },
3290 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
3291 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3292 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
3293 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3294 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3295 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
3296 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
3297 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
3298 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
3299 #ifdef CONFIG_SND_DEBUG
3300 { .modelname = "test", .config = ALC260_TEST },
3302 { .modelname = "auto", .config = ALC260_AUTO },
3306 static struct alc_config_preset alc260_presets[] = {
3308 .mixers = { alc260_base_output_mixer,
3310 alc260_pc_beep_mixer,
3311 alc260_capture_mixer },
3312 .init_verbs = { alc260_init_verbs },
3313 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3314 .dac_nids = alc260_dac_nids,
3315 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
3316 .adc_nids = alc260_adc_nids,
3317 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3318 .channel_mode = alc260_modes,
3319 .input_mux = &alc260_capture_source,
3322 .mixers = { alc260_base_output_mixer,
3324 alc260_capture_alt_mixer },
3325 .init_verbs = { alc260_hp_init_verbs },
3326 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3327 .dac_nids = alc260_dac_nids,
3328 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3329 .adc_nids = alc260_hp_adc_nids,
3330 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3331 .channel_mode = alc260_modes,
3332 .input_mux = &alc260_capture_source,
3334 [ALC260_HP_3013] = {
3335 .mixers = { alc260_hp_3013_mixer,
3337 alc260_capture_alt_mixer },
3338 .init_verbs = { alc260_hp_3013_init_verbs },
3339 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3340 .dac_nids = alc260_dac_nids,
3341 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3342 .adc_nids = alc260_hp_adc_nids,
3343 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3344 .channel_mode = alc260_modes,
3345 .input_mux = &alc260_capture_source,
3347 [ALC260_FUJITSU_S702X] = {
3348 .mixers = { alc260_fujitsu_mixer,
3349 alc260_capture_mixer },
3350 .init_verbs = { alc260_fujitsu_init_verbs },
3351 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3352 .dac_nids = alc260_dac_nids,
3353 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
3354 .adc_nids = alc260_dual_adc_nids,
3355 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3356 .channel_mode = alc260_modes,
3357 .input_mux = &alc260_fujitsu_capture_source,
3359 #ifdef CONFIG_SND_DEBUG
3361 .mixers = { alc260_test_mixer,
3362 alc260_capture_mixer },
3363 .init_verbs = { alc260_test_init_verbs },
3364 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
3365 .dac_nids = alc260_test_dac_nids,
3366 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
3367 .adc_nids = alc260_test_adc_nids,
3368 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3369 .channel_mode = alc260_modes,
3370 .input_mux = &alc260_test_capture_source,
3375 static int patch_alc260(struct hda_codec *codec)
3377 struct alc_spec *spec;
3378 int err, board_config;
3380 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3386 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
3387 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
3388 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
3389 board_config = ALC260_AUTO;
3392 if (board_config == ALC260_AUTO) {
3393 /* automatic parse from the BIOS config */
3394 err = alc260_parse_auto_config(codec);
3399 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3400 board_config = ALC260_BASIC;
3404 if (board_config != ALC260_AUTO)
3405 setup_preset(spec, &alc260_presets[board_config]);
3407 spec->stream_name_analog = "ALC260 Analog";
3408 spec->stream_analog_playback = &alc260_pcm_analog_playback;
3409 spec->stream_analog_capture = &alc260_pcm_analog_capture;
3411 spec->stream_name_digital = "ALC260 Digital";
3412 spec->stream_digital_playback = &alc260_pcm_digital_playback;
3413 spec->stream_digital_capture = &alc260_pcm_digital_capture;
3415 codec->patch_ops = alc_patch_ops;
3416 if (board_config == ALC260_AUTO)
3417 codec->patch_ops.init = alc260_auto_init;
3426 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3427 * configuration. Each pin widget can choose any input DACs and a mixer.
3428 * Each ADC is connected from a mixer of all inputs. This makes possible
3429 * 6-channel independent captures.
3431 * In addition, an independent DAC for the multi-playback (not used in this
3434 #define ALC882_DIGOUT_NID 0x06
3435 #define ALC882_DIGIN_NID 0x0a
3437 static struct hda_channel_mode alc882_ch_modes[1] = {
3441 static hda_nid_t alc882_dac_nids[4] = {
3442 /* front, rear, clfe, rear_surr */
3443 0x02, 0x03, 0x04, 0x05
3446 /* identical with ALC880 */
3447 #define alc882_adc_nids alc880_adc_nids
3448 #define alc882_adc_nids_alt alc880_adc_nids_alt
3451 /* FIXME: should be a matrix-type input source selection */
3453 static struct hda_input_mux alc882_capture_source = {
3457 { "Front Mic", 0x1 },
3463 #define alc882_mux_enum_info alc_mux_enum_info
3464 #define alc882_mux_enum_get alc_mux_enum_get
3466 static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3468 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3469 struct alc_spec *spec = codec->spec;
3470 const struct hda_input_mux *imux = spec->input_mux;
3471 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3472 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
3473 hda_nid_t nid = capture_mixers[adc_idx];
3474 unsigned int *cur_val = &spec->cur_mux[adc_idx];
3475 unsigned int i, idx;
3477 idx = ucontrol->value.enumerated.item[0];
3478 if (idx >= imux->num_items)
3479 idx = imux->num_items - 1;
3480 if (*cur_val == idx && ! codec->in_resume)
3482 for (i = 0; i < imux->num_items; i++) {
3483 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
3484 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3485 v | (imux->items[i].index << 8));
3494 static struct hda_verb alc882_sixstack_ch6_init[] = {
3495 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
3496 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3497 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3498 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3505 static struct hda_verb alc882_sixstack_ch8_init[] = {
3506 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3507 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3508 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3509 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3513 static struct hda_channel_mode alc882_sixstack_modes[2] = {
3514 { 6, alc882_sixstack_ch6_init },
3515 { 8, alc882_sixstack_ch8_init },
3518 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3519 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3521 static struct snd_kcontrol_new alc882_base_mixer[] = {
3522 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3523 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3524 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3525 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3526 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3527 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3528 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3529 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3530 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3531 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
3532 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3533 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3534 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3535 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3536 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3538 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3539 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3540 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3541 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
3542 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
3543 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3544 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3545 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3546 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3547 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3548 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3550 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3551 /* .name = "Capture Source", */
3552 .name = "Input Source",
3554 .info = alc882_mux_enum_info,
3555 .get = alc882_mux_enum_get,
3556 .put = alc882_mux_enum_put,
3561 static struct snd_kcontrol_new alc882_chmode_mixer[] = {
3563 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3564 .name = "Channel Mode",
3565 .info = alc_ch_mode_info,
3566 .get = alc_ch_mode_get,
3567 .put = alc_ch_mode_put,
3572 static struct hda_verb alc882_init_verbs[] = {
3573 /* Front mixer: unmute input/output amp left and right (volume = 0) */
3574 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3575 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3576 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3578 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3579 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3580 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3582 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3583 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3584 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3586 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3587 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3588 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3590 /* Front Pin: output 0 (0x0c) */
3591 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3592 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3593 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3594 /* Rear Pin: output 1 (0x0d) */
3595 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3596 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3597 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3598 /* CLFE Pin: output 2 (0x0e) */
3599 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3600 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3601 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
3602 /* Side Pin: output 3 (0x0f) */
3603 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3604 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3605 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
3606 /* Mic (rear) pin: input vref at 80% */
3607 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3608 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3609 /* Front Mic pin: input vref at 80% */
3610 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3611 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3612 /* Line In pin: input */
3613 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3614 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3615 /* Line-2 In: Headphone output (output 0 - 0x0c) */
3616 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3617 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3618 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3619 /* CD pin widget for input */
3620 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3622 /* FIXME: use matrix-type input source selection */
3623 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3624 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3625 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3626 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3627 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3628 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3630 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3631 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3632 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3633 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3635 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3636 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3637 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3638 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3639 /* ADC1: mute amp left and right */
3640 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3641 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3642 /* ADC2: mute amp left and right */
3643 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3644 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3645 /* ADC3: mute amp left and right */
3646 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3647 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3653 * generic initialization of ADC, input mixers and output mixers
3655 static struct hda_verb alc882_auto_init_verbs[] = {
3657 * Unmute ADC0-2 and set the default input to mic-in
3659 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3660 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3661 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3662 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3663 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3664 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3666 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3668 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3671 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3672 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3673 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3674 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3675 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3676 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3679 * Set up output mixers (0x0c - 0x0f)
3681 /* set vol=0 to output mixers */
3682 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3683 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3684 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3685 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3686 /* set up input amps for analog loopback */
3687 /* Amp Indices: DAC = 0, mixer = 1 */
3688 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3689 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3690 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3691 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3692 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3693 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3694 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3695 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3696 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3697 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3699 /* FIXME: use matrix-type input source selection */
3700 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3701 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3702 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3703 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3704 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3705 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3707 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3708 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3709 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3710 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3712 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3713 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3714 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3715 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3720 /* capture mixer elements */
3721 static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
3722 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3723 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3724 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
3725 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
3727 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3728 /* The multiple "Capture Source" controls confuse alsamixer
3729 * So call somewhat different..
3730 * FIXME: the controls appear in the "playback" view!
3732 /* .name = "Capture Source", */
3733 .name = "Input Source",
3735 .info = alc882_mux_enum_info,
3736 .get = alc882_mux_enum_get,
3737 .put = alc882_mux_enum_put,
3742 static struct snd_kcontrol_new alc882_capture_mixer[] = {
3743 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3744 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3745 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3746 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3747 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3748 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3751 /* The multiple "Capture Source" controls confuse alsamixer
3752 * So call somewhat different..
3753 * FIXME: the controls appear in the "playback" view!
3755 /* .name = "Capture Source", */
3756 .name = "Input Source",
3758 .info = alc882_mux_enum_info,
3759 .get = alc882_mux_enum_get,
3760 .put = alc882_mux_enum_put,
3765 /* pcm configuration: identiacal with ALC880 */
3766 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
3767 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
3768 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
3769 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
3772 * configuration and preset
3774 static struct hda_board_config alc882_cfg_tbl[] = {
3775 { .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
3776 { .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
3777 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */
3778 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
3779 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
3780 { .modelname = "auto", .config = ALC882_AUTO },
3784 static struct alc_config_preset alc882_presets[] = {
3785 [ALC882_3ST_DIG] = {
3786 .mixers = { alc882_base_mixer },
3787 .init_verbs = { alc882_init_verbs },
3788 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3789 .dac_nids = alc882_dac_nids,
3790 .dig_out_nid = ALC882_DIGOUT_NID,
3791 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3792 .adc_nids = alc882_adc_nids,
3793 .dig_in_nid = ALC882_DIGIN_NID,
3794 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
3795 .channel_mode = alc882_ch_modes,
3796 .input_mux = &alc882_capture_source,
3798 [ALC882_6ST_DIG] = {
3799 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
3800 .init_verbs = { alc882_init_verbs },
3801 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3802 .dac_nids = alc882_dac_nids,
3803 .dig_out_nid = ALC882_DIGOUT_NID,
3804 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3805 .adc_nids = alc882_adc_nids,
3806 .dig_in_nid = ALC882_DIGIN_NID,
3807 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
3808 .channel_mode = alc882_sixstack_modes,
3809 .input_mux = &alc882_capture_source,
3815 * BIOS auto configuration
3817 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
3818 hda_nid_t nid, int pin_type,
3822 struct alc_spec *spec = codec->spec;
3825 if (spec->multiout.dac_nids[dac_idx] == 0x25)
3828 idx = spec->multiout.dac_nids[dac_idx] - 2;
3830 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3831 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3832 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
3836 static void alc882_auto_init_multi_out(struct hda_codec *codec)
3838 struct alc_spec *spec = codec->spec;
3841 for (i = 0; i <= HDA_SIDE; i++) {
3842 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3844 alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3848 static void alc882_auto_init_hp_out(struct hda_codec *codec)
3850 struct alc_spec *spec = codec->spec;
3853 pin = spec->autocfg.hp_pin;
3854 if (pin) /* connect to front */
3855 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
3858 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
3859 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
3861 static void alc882_auto_init_analog_input(struct hda_codec *codec)
3863 struct alc_spec *spec = codec->spec;
3866 for (i = 0; i < AUTO_PIN_LAST; i++) {
3867 hda_nid_t nid = spec->autocfg.input_pins[i];
3868 if (alc882_is_input_pin(nid)) {
3869 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3870 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3871 if (nid != ALC882_PIN_CD_NID)
3872 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3878 /* almost identical with ALC880 parser... */
3879 static int alc882_parse_auto_config(struct hda_codec *codec)
3881 struct alc_spec *spec = codec->spec;
3882 int err = alc880_parse_auto_config(codec);
3887 /* hack - override the init verbs */
3888 spec->init_verbs[0] = alc882_auto_init_verbs;
3892 /* init callback for auto-configuration model -- overriding the default init */
3893 static int alc882_auto_init(struct hda_codec *codec)
3896 alc882_auto_init_multi_out(codec);
3897 alc882_auto_init_hp_out(codec);
3898 alc882_auto_init_analog_input(codec);
3903 * ALC882 Headphone poll in 3.5.1a or 3.5.2
3906 static int patch_alc882(struct hda_codec *codec)
3908 struct alc_spec *spec;
3909 int err, board_config;
3911 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3917 board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
3919 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
3920 printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
3921 board_config = ALC882_AUTO;
3924 if (board_config == ALC882_AUTO) {
3925 /* automatic parse from the BIOS config */
3926 err = alc882_parse_auto_config(codec);
3931 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3932 board_config = ALC882_3ST_DIG;
3936 if (board_config != ALC882_AUTO)
3937 setup_preset(spec, &alc882_presets[board_config]);
3939 spec->stream_name_analog = "ALC882 Analog";
3940 spec->stream_analog_playback = &alc882_pcm_analog_playback;
3941 spec->stream_analog_capture = &alc882_pcm_analog_capture;
3943 spec->stream_name_digital = "ALC882 Digital";
3944 spec->stream_digital_playback = &alc882_pcm_digital_playback;
3945 spec->stream_digital_capture = &alc882_pcm_digital_capture;
3947 if (! spec->adc_nids && spec->input_mux) {
3948 /* check whether NID 0x07 is valid */
3949 unsigned int wcap = get_wcaps(codec, 0x07);
3950 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3951 if (wcap != AC_WID_AUD_IN) {
3952 spec->adc_nids = alc882_adc_nids_alt;
3953 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
3954 spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
3957 spec->adc_nids = alc882_adc_nids;
3958 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
3959 spec->mixers[spec->num_mixers] = alc882_capture_mixer;
3964 codec->patch_ops = alc_patch_ops;
3965 if (board_config == ALC882_AUTO)
3966 codec->patch_ops.init = alc882_auto_init;
3975 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
3976 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
3978 #define alc262_dac_nids alc260_dac_nids
3979 #define alc262_adc_nids alc882_adc_nids
3980 #define alc262_adc_nids_alt alc882_adc_nids_alt
3982 #define alc262_modes alc260_modes
3983 #define alc262_capture_source alc882_capture_source
3985 static struct snd_kcontrol_new alc262_base_mixer[] = {
3986 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3987 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3988 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3989 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3990 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3991 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3992 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3993 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3994 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3995 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
3996 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3997 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3998 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
3999 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4000 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
4001 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
4002 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4003 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4005 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4006 .name = "Capture Source",
4008 .info = alc882_mux_enum_info,
4009 .get = alc882_mux_enum_get,
4010 .put = alc882_mux_enum_put,
4015 #define alc262_capture_mixer alc882_capture_mixer
4016 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
4019 * generic initialization of ADC, input mixers and output mixers
4021 static struct hda_verb alc262_init_verbs[] = {
4023 * Unmute ADC0-2 and set the default input to mic-in
4025 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4026 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4027 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4028 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4029 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4030 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4032 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4034 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4037 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4038 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4039 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4040 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4041 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4042 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4045 * Set up output mixers (0x0c - 0x0e)
4047 /* set vol=0 to output mixers */
4048 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4049 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4050 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4051 /* set up input amps for analog loopback */
4052 /* Amp Indices: DAC = 0, mixer = 1 */
4053 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4054 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4055 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4056 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4057 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4058 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4060 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4061 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
4062 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4063 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4064 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4065 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
4067 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4068 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4069 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4070 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4071 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
4073 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
4074 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
4076 /* FIXME: use matrix-type input source selection */
4077 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4078 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4079 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4080 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4081 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4082 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4084 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4085 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4086 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4087 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4089 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4090 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4091 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4092 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4097 /* add playback controls from the parsed DAC table */
4098 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4103 spec->multiout.num_dacs = 1; /* only use one dac */
4104 spec->multiout.dac_nids = spec->private_dac_nids;
4105 spec->multiout.dac_nids[0] = 2;
4107 nid = cfg->line_out_pins[0];
4109 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
4110 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4112 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
4113 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4117 nid = cfg->speaker_pin;
4120 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4121 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4123 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4124 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4127 if (! cfg->line_out_pins[0])
4128 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4129 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4131 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4132 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4138 /* spec->multiout.hp_nid = 2; */
4140 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4141 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4143 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4144 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4147 if (! cfg->line_out_pins[0])
4148 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4149 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4151 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4152 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4159 /* identical with ALC880 */
4160 #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
4163 * generic initialization of ADC, input mixers and output mixers
4165 static struct hda_verb alc262_volume_init_verbs[] = {
4167 * Unmute ADC0-2 and set the default input to mic-in
4169 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4170 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4171 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4172 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4173 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4174 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4176 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4178 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4181 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4182 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4183 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4184 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4185 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4186 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4189 * Set up output mixers (0x0c - 0x0f)
4191 /* set vol=0 to output mixers */
4192 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4193 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4194 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4196 /* set up input amps for analog loopback */
4197 /* Amp Indices: DAC = 0, mixer = 1 */
4198 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4199 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4200 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4201 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4202 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4203 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4205 /* FIXME: use matrix-type input source selection */
4206 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4207 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4208 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4209 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4210 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4211 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4213 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4214 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4215 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4216 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4218 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4219 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4220 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4221 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4226 /* pcm configuration: identiacal with ALC880 */
4227 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
4228 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
4229 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
4230 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
4233 * BIOS auto configuration
4235 static int alc262_parse_auto_config(struct hda_codec *codec)
4237 struct alc_spec *spec = codec->spec;
4239 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
4241 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4242 alc262_ignore)) < 0)
4244 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4245 ! spec->autocfg.hp_pin)
4246 return 0; /* can't find valid BIOS pin config */
4247 if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4248 (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4251 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4253 if (spec->autocfg.dig_out_pin)
4254 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
4255 if (spec->autocfg.dig_in_pin)
4256 spec->dig_in_nid = ALC262_DIGIN_NID;
4258 if (spec->kctl_alloc)
4259 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4261 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
4262 spec->input_mux = &spec->private_imux;
4267 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
4268 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
4269 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
4272 /* init callback for auto-configuration model -- overriding the default init */
4273 static int alc262_auto_init(struct hda_codec *codec)
4276 alc262_auto_init_multi_out(codec);
4277 alc262_auto_init_hp_out(codec);
4278 alc262_auto_init_analog_input(codec);
4283 * configuration and preset
4285 static struct hda_board_config alc262_cfg_tbl[] = {
4286 { .modelname = "basic", .config = ALC262_BASIC },
4287 { .modelname = "auto", .config = ALC262_AUTO },
4291 static struct alc_config_preset alc262_presets[] = {
4293 .mixers = { alc262_base_mixer },
4294 .init_verbs = { alc262_init_verbs },
4295 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
4296 .dac_nids = alc262_dac_nids,
4298 .num_channel_mode = ARRAY_SIZE(alc262_modes),
4299 .channel_mode = alc262_modes,
4300 .input_mux = &alc262_capture_source,
4304 static int patch_alc262(struct hda_codec *codec)
4306 struct alc_spec *spec;
4310 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4316 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
4319 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4320 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4321 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4322 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4326 board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
4327 if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
4328 printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4329 board_config = ALC262_AUTO;
4332 if (board_config == ALC262_AUTO) {
4333 /* automatic parse from the BIOS config */
4334 err = alc262_parse_auto_config(codec);
4339 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4340 board_config = ALC262_BASIC;
4344 if (board_config != ALC262_AUTO)
4345 setup_preset(spec, &alc262_presets[board_config]);
4347 spec->stream_name_analog = "ALC262 Analog";
4348 spec->stream_analog_playback = &alc262_pcm_analog_playback;
4349 spec->stream_analog_capture = &alc262_pcm_analog_capture;
4351 spec->stream_name_digital = "ALC262 Digital";
4352 spec->stream_digital_playback = &alc262_pcm_digital_playback;
4353 spec->stream_digital_capture = &alc262_pcm_digital_capture;
4355 if (! spec->adc_nids && spec->input_mux) {
4356 /* check whether NID 0x07 is valid */
4357 unsigned int wcap = get_wcaps(codec, 0x07);
4359 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4360 if (wcap != AC_WID_AUD_IN) {
4361 spec->adc_nids = alc262_adc_nids_alt;
4362 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
4363 spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
4366 spec->adc_nids = alc262_adc_nids;
4367 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
4368 spec->mixers[spec->num_mixers] = alc262_capture_mixer;
4373 codec->patch_ops = alc_patch_ops;
4374 if (board_config == ALC262_AUTO)
4375 codec->patch_ops.init = alc262_auto_init;
4382 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4386 * set the path ways for 2 channel output
4387 * need to set the codec line out and mic 1 pin widgets to inputs
4389 static struct hda_verb alc861_threestack_ch2_init[] = {
4390 /* set pin widget 1Ah (line in) for input */
4391 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4392 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4393 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4395 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
4396 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
4397 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
4402 * need to set the codec line out and mic 1 pin widgets to outputs
4404 static struct hda_verb alc861_threestack_ch6_init[] = {
4405 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4406 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4407 /* set pin widget 18h (mic1) for output (CLFE)*/
4408 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4410 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
4411 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
4413 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
4414 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
4415 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
4419 static struct hda_channel_mode alc861_threestack_modes[2] = {
4420 { 2, alc861_threestack_ch2_init },
4421 { 6, alc861_threestack_ch6_init },
4426 static struct snd_kcontrol_new alc861_base_mixer[] = {
4427 /* output mixer control */
4428 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4429 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4430 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4431 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4432 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
4434 /*Input mixer control */
4435 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4436 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4437 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4438 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4439 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4440 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4441 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4442 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4443 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4444 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4446 /* Capture mixer control */
4447 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4448 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4450 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4451 .name = "Capture Source",
4453 .info = alc_mux_enum_info,
4454 .get = alc_mux_enum_get,
4455 .put = alc_mux_enum_put,
4460 static struct snd_kcontrol_new alc861_3ST_mixer[] = {
4461 /* output mixer control */
4462 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4463 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4464 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4465 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4466 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4468 /* Input mixer control */
4469 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4470 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4471 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4472 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4473 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4474 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4475 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4476 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4477 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4478 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4480 /* Capture mixer control */
4481 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4482 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4485 .name = "Capture Source",
4487 .info = alc_mux_enum_info,
4488 .get = alc_mux_enum_get,
4489 .put = alc_mux_enum_put,
4492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4493 .name = "Channel Mode",
4494 .info = alc_ch_mode_info,
4495 .get = alc_ch_mode_get,
4496 .put = alc_ch_mode_put,
4497 .private_value = ARRAY_SIZE(alc861_threestack_modes),
4503 * generic initialization of ADC, input mixers and output mixers
4505 static struct hda_verb alc861_base_init_verbs[] = {
4507 * Unmute ADC0 and set the default input to mic-in
4509 /* port-A for surround (rear panel) */
4510 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4511 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
4512 /* port-B for mic-in (rear panel) with vref */
4513 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4514 /* port-C for line-in (rear panel) */
4515 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4516 /* port-D for Front */
4517 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4518 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4519 /* port-E for HP out (front panel) */
4520 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4521 /* route front PCM to HP */
4522 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4523 /* port-F for mic-in (front panel) with vref */
4524 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4525 /* port-G for CLFE (rear panel) */
4526 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4527 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
4528 /* port-H for side (rear panel) */
4529 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4530 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
4532 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4533 /* route front mic to ADC1*/
4534 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4535 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4537 /* Unmute DAC0~3 & spdif out*/
4538 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4539 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4540 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4541 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4542 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4544 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4545 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4546 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4547 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4548 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4550 /* Unmute Stereo Mixer 15 */
4551 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4552 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4553 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4554 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4556 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4557 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4558 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4559 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4560 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4561 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4562 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4563 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4564 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4565 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4570 static struct hda_verb alc861_threestack_init_verbs[] = {
4572 * Unmute ADC0 and set the default input to mic-in
4574 /* port-A for surround (rear panel) */
4575 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4576 /* port-B for mic-in (rear panel) with vref */
4577 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4578 /* port-C for line-in (rear panel) */
4579 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4580 /* port-D for Front */
4581 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4582 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4583 /* port-E for HP out (front panel) */
4584 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4585 /* route front PCM to HP */
4586 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4587 /* port-F for mic-in (front panel) with vref */
4588 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4589 /* port-G for CLFE (rear panel) */
4590 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4591 /* port-H for side (rear panel) */
4592 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4594 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4595 /* route front mic to ADC1*/
4596 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4597 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4598 /* Unmute DAC0~3 & spdif out*/
4599 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4600 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4601 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4602 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4603 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4605 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4606 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4607 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4608 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4609 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4611 /* Unmute Stereo Mixer 15 */
4612 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4613 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4614 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4615 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4617 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4618 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4619 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4620 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4621 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4622 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4623 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4624 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4625 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4626 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4630 * generic initialization of ADC, input mixers and output mixers
4632 static struct hda_verb alc861_auto_init_verbs[] = {
4634 * Unmute ADC0 and set the default input to mic-in
4636 // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4637 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4639 /* Unmute DAC0~3 & spdif out*/
4640 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4641 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4642 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4643 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4644 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4646 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4647 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4648 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4649 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4650 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4652 /* Unmute Stereo Mixer 15 */
4653 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4654 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4655 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4656 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
4658 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4659 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4660 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4661 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4662 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4663 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4664 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4665 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4667 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4668 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4669 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4670 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4671 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4672 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4673 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4674 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4676 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1
4681 /* pcm configuration: identiacal with ALC880 */
4682 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
4683 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
4684 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
4685 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
4688 #define ALC861_DIGOUT_NID 0x07
4690 static struct hda_channel_mode alc861_8ch_modes[1] = {
4694 static hda_nid_t alc861_dac_nids[4] = {
4695 /* front, surround, clfe, side */
4696 0x03, 0x06, 0x05, 0x04
4699 static hda_nid_t alc861_adc_nids[1] = {
4704 static struct hda_input_mux alc861_capture_source = {
4708 { "Front Mic", 0x3 },
4715 /* fill in the dac_nids table from the parsed pin configuration */
4716 static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4721 spec->multiout.dac_nids = spec->private_dac_nids;
4722 for (i = 0; i < cfg->line_outs; i++) {
4723 nid = cfg->line_out_pins[i];
4725 if (i >= ARRAY_SIZE(alc861_dac_nids))
4727 spec->multiout.dac_nids[i] = alc861_dac_nids[i];
4730 spec->multiout.num_dacs = cfg->line_outs;
4734 /* add playback controls from the parsed DAC table */
4735 static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
4736 const struct auto_pin_cfg *cfg)
4739 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
4743 for (i = 0; i < cfg->line_outs; i++) {
4744 nid = spec->multiout.dac_nids[i];
4749 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
4750 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
4752 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
4753 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4756 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
4757 if (nid == alc861_dac_nids[idx])
4759 sprintf(name, "%s Playback Switch", chname[idx]);
4760 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4761 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4768 static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
4776 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
4778 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4779 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4781 spec->multiout.hp_nid = nid;
4786 /* create playback/capture controls for input pins */
4787 static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4789 struct hda_input_mux *imux = &spec->private_imux;
4790 int i, err, idx, idx1;
4792 for (i = 0; i < AUTO_PIN_LAST; i++) {
4793 switch(cfg->input_pins[i]) {
4818 err = new_analog_input(spec, cfg->input_pins[i],
4819 auto_pin_cfg_labels[i], idx, 0x15);
4823 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
4824 imux->items[imux->num_items].index = idx1;
4830 static struct snd_kcontrol_new alc861_capture_mixer[] = {
4831 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4832 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4835 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4836 /* The multiple "Capture Source" controls confuse alsamixer
4837 * So call somewhat different..
4838 *FIXME: the controls appear in the "playback" view!
4840 /* .name = "Capture Source", */
4841 .name = "Input Source",
4843 .info = alc_mux_enum_info,
4844 .get = alc_mux_enum_get,
4845 .put = alc_mux_enum_put,
4850 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
4851 int pin_type, int dac_idx)
4855 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4856 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4860 static void alc861_auto_init_multi_out(struct hda_codec *codec)
4862 struct alc_spec *spec = codec->spec;
4865 for (i = 0; i < spec->autocfg.line_outs; i++) {
4866 hda_nid_t nid = spec->autocfg.line_out_pins[i];
4868 alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
4872 static void alc861_auto_init_hp_out(struct hda_codec *codec)
4874 struct alc_spec *spec = codec->spec;
4877 pin = spec->autocfg.hp_pin;
4878 if (pin) /* connect to front */
4879 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
4882 static void alc861_auto_init_analog_input(struct hda_codec *codec)
4884 struct alc_spec *spec = codec->spec;
4887 for (i = 0; i < AUTO_PIN_LAST; i++) {
4888 hda_nid_t nid = spec->autocfg.input_pins[i];
4889 if ((nid>=0x0c) && (nid <=0x11)) {
4890 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4891 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4896 /* parse the BIOS configuration and set up the alc_spec */
4897 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4898 static int alc861_parse_auto_config(struct hda_codec *codec)
4900 struct alc_spec *spec = codec->spec;
4902 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
4904 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4905 alc861_ignore)) < 0)
4907 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4908 ! spec->autocfg.hp_pin)
4909 return 0; /* can't find valid BIOS pin config */
4911 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
4912 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4913 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
4914 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4917 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4919 if (spec->autocfg.dig_out_pin)
4920 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
4922 if (spec->kctl_alloc)
4923 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4925 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
4927 spec->input_mux = &spec->private_imux;
4929 spec->adc_nids = alc861_adc_nids;
4930 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
4931 spec->mixers[spec->num_mixers] = alc861_capture_mixer;
4937 /* init callback for auto-configuration model -- overriding the default init */
4938 static int alc861_auto_init(struct hda_codec *codec)
4941 alc861_auto_init_multi_out(codec);
4942 alc861_auto_init_hp_out(codec);
4943 alc861_auto_init_analog_input(codec);
4950 * configuration and preset
4952 static struct hda_board_config alc861_cfg_tbl[] = {
4953 { .modelname = "3stack", .config = ALC861_3ST },
4954 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
4955 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
4956 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
4957 { .modelname = "auto", .config = ALC861_AUTO },
4961 static struct alc_config_preset alc861_presets[] = {
4963 .mixers = { alc861_3ST_mixer },
4964 .init_verbs = { alc861_threestack_init_verbs },
4965 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4966 .dac_nids = alc861_dac_nids,
4967 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4968 .channel_mode = alc861_threestack_modes,
4969 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4970 .adc_nids = alc861_adc_nids,
4971 .input_mux = &alc861_capture_source,
4973 [ALC861_3ST_DIG] = {
4974 .mixers = { alc861_base_mixer },
4975 .init_verbs = { alc861_threestack_init_verbs },
4976 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4977 .dac_nids = alc861_dac_nids,
4978 .dig_out_nid = ALC861_DIGOUT_NID,
4979 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4980 .channel_mode = alc861_threestack_modes,
4981 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4982 .adc_nids = alc861_adc_nids,
4983 .input_mux = &alc861_capture_source,
4985 [ALC861_6ST_DIG] = {
4986 .mixers = { alc861_base_mixer },
4987 .init_verbs = { alc861_base_init_verbs },
4988 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4989 .dac_nids = alc861_dac_nids,
4990 .dig_out_nid = ALC861_DIGOUT_NID,
4991 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
4992 .channel_mode = alc861_8ch_modes,
4993 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4994 .adc_nids = alc861_adc_nids,
4995 .input_mux = &alc861_capture_source,
5000 static int patch_alc861(struct hda_codec *codec)
5002 struct alc_spec *spec;
5006 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
5012 board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
5013 if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
5014 printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
5015 board_config = ALC861_AUTO;
5018 if (board_config == ALC861_AUTO) {
5019 /* automatic parse from the BIOS config */
5020 err = alc861_parse_auto_config(codec);
5025 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
5026 board_config = ALC861_3ST_DIG;
5030 if (board_config != ALC861_AUTO)
5031 setup_preset(spec, &alc861_presets[board_config]);
5033 spec->stream_name_analog = "ALC861 Analog";
5034 spec->stream_analog_playback = &alc861_pcm_analog_playback;
5035 spec->stream_analog_capture = &alc861_pcm_analog_capture;
5037 spec->stream_name_digital = "ALC861 Digital";
5038 spec->stream_digital_playback = &alc861_pcm_digital_playback;
5039 spec->stream_digital_capture = &alc861_pcm_digital_capture;
5041 codec->patch_ops = alc_patch_ops;
5042 if (board_config == ALC861_AUTO)
5043 codec->patch_ops.init = alc861_auto_init;
5051 struct hda_codec_preset snd_hda_preset_realtek[] = {
5052 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
5053 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
5054 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
5055 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
5056 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
5057 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
5058 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },