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 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
311 alc_pin_mode_values[val]);
315 #define ALC_PIN_MODE(xname, nid, dir) \
316 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
317 .info = alc_pin_mode_info, \
318 .get = alc_pin_mode_get, \
319 .put = alc_pin_mode_put, \
320 .private_value = nid | (dir<<16) }
323 * set up from the preset table
325 static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset)
329 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
330 spec->mixers[spec->num_mixers++] = preset->mixers[i];
331 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++)
332 spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
334 spec->channel_mode = preset->channel_mode;
335 spec->num_channel_mode = preset->num_channel_mode;
337 spec->multiout.max_channels = spec->channel_mode[0].channels;
339 spec->multiout.num_dacs = preset->num_dacs;
340 spec->multiout.dac_nids = preset->dac_nids;
341 spec->multiout.dig_out_nid = preset->dig_out_nid;
342 spec->multiout.hp_nid = preset->hp_nid;
344 spec->input_mux = preset->input_mux;
346 spec->num_adc_nids = preset->num_adc_nids;
347 spec->adc_nids = preset->adc_nids;
348 spec->dig_in_nid = preset->dig_in_nid;
352 * ALC880 3-stack model
354 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
355 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
359 static hda_nid_t alc880_dac_nids[4] = {
360 /* front, rear, clfe, rear_surr */
361 0x02, 0x05, 0x04, 0x03
364 static hda_nid_t alc880_adc_nids[3] = {
369 /* The datasheet says the node 0x07 is connected from inputs,
370 * but it shows zero connection in the real implementation on some devices.
371 * Note: this is a 915GAV bug, fixed on 915GLV
373 static hda_nid_t alc880_adc_nids_alt[2] = {
378 #define ALC880_DIGOUT_NID 0x06
379 #define ALC880_DIGIN_NID 0x0a
381 static struct hda_input_mux alc880_capture_source = {
385 { "Front Mic", 0x3 },
391 /* channel source setting (2/6 channel selection for 3-stack) */
393 static struct hda_verb alc880_threestack_ch2_init[] = {
394 /* set line-in to input, mute it */
395 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
396 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
397 /* set mic-in to input vref 80%, mute it */
398 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
399 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
404 static struct hda_verb alc880_threestack_ch6_init[] = {
405 /* set line-in to output, unmute it */
406 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
407 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
408 /* set mic-in to output, unmute it */
409 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
410 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
414 static struct hda_channel_mode alc880_threestack_modes[2] = {
415 { 2, alc880_threestack_ch2_init },
416 { 6, alc880_threestack_ch6_init },
419 static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
420 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
421 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
422 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
423 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
424 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
425 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
426 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
427 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
428 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
429 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
430 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
431 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
432 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
433 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
434 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
435 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
436 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
437 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
438 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
441 .name = "Channel Mode",
442 .info = alc_ch_mode_info,
443 .get = alc_ch_mode_get,
444 .put = alc_ch_mode_put,
449 /* capture mixer elements */
450 static struct snd_kcontrol_new alc880_capture_mixer[] = {
451 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
452 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
453 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
454 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
455 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
456 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
458 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
459 /* The multiple "Capture Source" controls confuse alsamixer
460 * So call somewhat different..
461 * FIXME: the controls appear in the "playback" view!
463 /* .name = "Capture Source", */
464 .name = "Input Source",
466 .info = alc_mux_enum_info,
467 .get = alc_mux_enum_get,
468 .put = alc_mux_enum_put,
473 /* capture mixer elements (in case NID 0x07 not available) */
474 static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
475 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
476 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
477 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
478 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
481 /* The multiple "Capture Source" controls confuse alsamixer
482 * So call somewhat different..
483 * FIXME: the controls appear in the "playback" view!
485 /* .name = "Capture Source", */
486 .name = "Input Source",
488 .info = alc_mux_enum_info,
489 .get = alc_mux_enum_get,
490 .put = alc_mux_enum_put,
498 * ALC880 5-stack model
500 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
501 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
502 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
505 /* additional mixers to alc880_three_stack_mixer */
506 static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
507 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
508 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
512 /* channel source setting (6/8 channel selection for 5-stack) */
514 static struct hda_verb alc880_fivestack_ch6_init[] = {
515 /* set line-in to input, mute it */
516 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
517 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
522 static struct hda_verb alc880_fivestack_ch8_init[] = {
523 /* set line-in to output, unmute it */
524 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
525 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
529 static struct hda_channel_mode alc880_fivestack_modes[2] = {
530 { 6, alc880_fivestack_ch6_init },
531 { 8, alc880_fivestack_ch8_init },
536 * ALC880 6-stack model
538 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
539 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
540 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
543 static hda_nid_t alc880_6st_dac_nids[4] = {
544 /* front, rear, clfe, rear_surr */
545 0x02, 0x03, 0x04, 0x05
548 static struct hda_input_mux alc880_6stack_capture_source = {
552 { "Front Mic", 0x1 },
558 /* fixed 8-channels */
559 static struct hda_channel_mode alc880_sixstack_modes[1] = {
563 static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
564 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
565 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
566 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
567 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
568 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
569 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
570 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
571 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
572 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
573 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
574 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
575 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
576 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
577 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
578 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
579 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
580 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
581 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
582 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
583 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
586 .name = "Channel Mode",
587 .info = alc_ch_mode_info,
588 .get = alc_ch_mode_get,
589 .put = alc_ch_mode_put,
598 * W810 has rear IO for:
601 * Center/LFE (DAC 04)
604 * The system also has a pair of internal speakers, and a headphone jack.
605 * These are both connected to Line2 on the codec, hence to DAC 02.
607 * There is a variable resistor to control the speaker or headphone
608 * volume. This is a hardware-only device without a software API.
610 * Plugging headphones in will disable the internal speakers. This is
611 * implemented in hardware, not via the driver using jack sense. In
612 * a similar fashion, plugging into the rear socket marked "front" will
613 * disable both the speakers and headphones.
615 * For input, there's a microphone jack, and an "audio in" jack.
616 * These may not do anything useful with this driver yet, because I
617 * haven't setup any initialization verbs for these yet...
620 static hda_nid_t alc880_w810_dac_nids[3] = {
621 /* front, rear/surround, clfe */
625 /* fixed 6 channels */
626 static struct hda_channel_mode alc880_w810_modes[1] = {
630 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
631 static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
632 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
633 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
634 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
635 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
636 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
637 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
638 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
639 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
640 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
648 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
649 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
652 static hda_nid_t alc880_z71v_dac_nids[1] = {
655 #define ALC880_Z71V_HP_DAC 0x03
657 /* fixed 2 channels */
658 static struct hda_channel_mode alc880_2_jack_modes[1] = {
662 static struct snd_kcontrol_new alc880_z71v_mixer[] = {
663 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
664 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
665 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
666 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
667 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
668 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
669 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
670 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
679 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
680 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
683 static hda_nid_t alc880_f1734_dac_nids[1] = {
686 #define ALC880_F1734_HP_DAC 0x02
688 static struct snd_kcontrol_new alc880_f1734_mixer[] = {
689 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
690 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
691 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
692 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
693 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
694 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
695 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
696 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
705 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
706 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
707 * Mic = 0x18, Line = 0x1a
710 #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
711 #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
713 static struct snd_kcontrol_new alc880_asus_mixer[] = {
714 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
715 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
716 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
717 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
718 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
719 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
720 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
721 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
722 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
723 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
724 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
725 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
726 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
727 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
730 .name = "Channel Mode",
731 .info = alc_ch_mode_info,
732 .get = alc_ch_mode_get,
733 .put = alc_ch_mode_put,
740 * ALC880 ASUS W1V model
742 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
743 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
744 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
747 /* additional mixers to alc880_asus_mixer */
748 static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
749 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
750 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
754 /* additional mixers to alc880_asus_mixer */
755 static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
756 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
757 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
762 static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
763 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
764 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
765 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
766 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
767 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
768 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
769 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
770 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
771 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
773 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
774 /* The multiple "Capture Source" controls confuse alsamixer
775 * So call somewhat different..
776 * FIXME: the controls appear in the "playback" view!
778 /* .name = "Capture Source", */
779 .name = "Input Source",
781 .info = alc_mux_enum_info,
782 .get = alc_mux_enum_get,
783 .put = alc_mux_enum_put,
789 * build control elements
791 static int alc_build_controls(struct hda_codec *codec)
793 struct alc_spec *spec = codec->spec;
797 for (i = 0; i < spec->num_mixers; i++) {
798 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
803 if (spec->multiout.dig_out_nid) {
804 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
808 if (spec->dig_in_nid) {
809 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
818 * initialize the codec volumes, etc
822 * generic initialization of ADC, input mixers and output mixers
824 static struct hda_verb alc880_volume_init_verbs[] = {
826 * Unmute ADC0-2 and set the default input to mic-in
828 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
829 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
830 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
831 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
832 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
833 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
835 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
837 * Note: PASD motherboards uses the Line In 2 as the input for front panel
840 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
841 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
842 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
843 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
844 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
845 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
848 * Set up output mixers (0x0c - 0x0f)
850 /* set vol=0 to output mixers */
851 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
852 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
853 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
854 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
855 /* set up input amps for analog loopback */
856 /* Amp Indices: DAC = 0, mixer = 1 */
857 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
858 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
859 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
860 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
861 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
862 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
863 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
864 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
870 * 3-stack pin configuration:
871 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
873 static struct hda_verb alc880_pin_3stack_init_verbs[] = {
875 * preset connection lists of input pins
876 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
878 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
879 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
880 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
883 * Set pin mode and muting
885 /* set front pin widgets 0x14 for output */
886 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
887 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
888 /* Mic1 (rear panel) pin widget for input and vref at 80% */
889 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
890 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
891 /* Mic2 (as headphone out) for HP output */
892 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
893 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
894 /* Line In pin widget for input */
895 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
896 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
897 /* Line2 (as front mic) pin widget for input and vref at 80% */
898 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
899 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
900 /* CD pin widget for input */
901 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
907 * 5-stack pin configuration:
908 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
909 * line-in/side = 0x1a, f-mic = 0x1b
911 static struct hda_verb alc880_pin_5stack_init_verbs[] = {
913 * preset connection lists of input pins
914 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
916 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
917 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
920 * Set pin mode and muting
922 /* set pin widgets 0x14-0x17 for output */
923 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
924 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
925 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
926 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
927 /* unmute pins for output (no gain on this amp) */
928 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
929 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
930 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
931 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
933 /* Mic1 (rear panel) pin widget for input and vref at 80% */
934 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
935 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
936 /* Mic2 (as headphone out) for HP output */
937 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
938 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
939 /* Line In pin widget for input */
940 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
941 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
942 /* Line2 (as front mic) pin widget for input and vref at 80% */
943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
944 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
945 /* CD pin widget for input */
946 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
952 * W810 pin configuration:
953 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
955 static struct hda_verb alc880_pin_w810_init_verbs[] = {
956 /* hphone/speaker input selector: front DAC */
957 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
959 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
960 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
961 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
962 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
963 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
964 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
966 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
967 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
973 * Z71V pin configuration:
974 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
976 static struct hda_verb alc880_pin_z71v_init_verbs[] = {
977 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
978 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
979 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
980 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
982 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
983 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
984 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
985 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
991 * 6-stack pin configuration:
992 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
993 * line = 0x1a, HP = 0x1b
995 static struct hda_verb alc880_pin_6stack_init_verbs[] = {
996 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
998 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
999 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1000 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1001 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1002 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1003 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1004 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1005 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1007 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1008 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1009 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1010 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1011 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1012 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1013 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1014 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1015 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1022 * F1734 pin configuration:
1023 * HP = 0x14, speaker-out = 0x15, mic = 0x18
1025 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
1026 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1027 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1028 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1029 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1031 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1032 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1033 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1034 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1036 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1037 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1038 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1039 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1040 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1041 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1042 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1043 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1044 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1051 * ASUS pin configuration:
1052 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
1054 static struct hda_verb alc880_pin_asus_init_verbs[] = {
1055 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
1056 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
1057 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
1058 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
1060 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1061 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1062 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1063 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1064 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1065 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1066 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1067 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1069 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1070 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1071 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1072 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1073 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1074 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1075 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1076 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1077 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1082 /* Enable GPIO mask and set output */
1083 static struct hda_verb alc880_gpio1_init_verbs[] = {
1084 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
1085 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
1086 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1091 /* Enable GPIO mask and set output */
1092 static struct hda_verb alc880_gpio2_init_verbs[] = {
1093 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
1094 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
1095 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1100 /* Clevo m520g init */
1101 static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1102 /* headphone output */
1103 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1105 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1106 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1108 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1109 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1111 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1112 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1113 /* Mic1 (rear panel) */
1114 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1115 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1116 /* Mic2 (front panel) */
1117 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1118 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1120 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1121 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1122 /* change to EAPD mode */
1123 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1124 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
1129 static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1130 /* Headphone output */
1131 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1133 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1134 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1136 /* Line In pin widget for input */
1137 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1138 /* CD pin widget for input */
1139 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1140 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1141 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1143 /* change to EAPD mode */
1144 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1145 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
1153 static int alc_init(struct hda_codec *codec)
1155 struct alc_spec *spec = codec->spec;
1158 for (i = 0; i < spec->num_init_verbs; i++)
1159 snd_hda_sequence_write(codec, spec->init_verbs[i]);
1167 static int alc_resume(struct hda_codec *codec)
1169 struct alc_spec *spec = codec->spec;
1173 for (i = 0; i < spec->num_mixers; i++)
1174 snd_hda_resume_ctls(codec, spec->mixers[i]);
1175 if (spec->multiout.dig_out_nid)
1176 snd_hda_resume_spdif_out(codec);
1177 if (spec->dig_in_nid)
1178 snd_hda_resume_spdif_in(codec);
1185 * Analog playback callbacks
1187 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
1188 struct hda_codec *codec,
1189 struct snd_pcm_substream *substream)
1191 struct alc_spec *spec = codec->spec;
1192 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
1195 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1196 struct hda_codec *codec,
1197 unsigned int stream_tag,
1198 unsigned int format,
1199 struct snd_pcm_substream *substream)
1201 struct alc_spec *spec = codec->spec;
1202 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
1206 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
1207 struct hda_codec *codec,
1208 struct snd_pcm_substream *substream)
1210 struct alc_spec *spec = codec->spec;
1211 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1217 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1218 struct hda_codec *codec,
1219 struct snd_pcm_substream *substream)
1221 struct alc_spec *spec = codec->spec;
1222 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1225 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1226 struct hda_codec *codec,
1227 struct snd_pcm_substream *substream)
1229 struct alc_spec *spec = codec->spec;
1230 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1236 static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1237 struct hda_codec *codec,
1238 unsigned int stream_tag,
1239 unsigned int format,
1240 struct snd_pcm_substream *substream)
1242 struct alc_spec *spec = codec->spec;
1244 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1245 stream_tag, 0, format);
1249 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1250 struct hda_codec *codec,
1251 struct snd_pcm_substream *substream)
1253 struct alc_spec *spec = codec->spec;
1255 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
1262 static struct hda_pcm_stream alc880_pcm_analog_playback = {
1266 /* NID is set in alc_build_pcms */
1268 .open = alc880_playback_pcm_open,
1269 .prepare = alc880_playback_pcm_prepare,
1270 .cleanup = alc880_playback_pcm_cleanup
1274 static struct hda_pcm_stream alc880_pcm_analog_capture = {
1278 /* NID is set in alc_build_pcms */
1280 .prepare = alc880_capture_pcm_prepare,
1281 .cleanup = alc880_capture_pcm_cleanup
1285 static struct hda_pcm_stream alc880_pcm_digital_playback = {
1289 /* NID is set in alc_build_pcms */
1291 .open = alc880_dig_playback_pcm_open,
1292 .close = alc880_dig_playback_pcm_close
1296 static struct hda_pcm_stream alc880_pcm_digital_capture = {
1300 /* NID is set in alc_build_pcms */
1303 /* Used by alc_build_pcms to flag that a PCM has no playback stream */
1304 static struct hda_pcm_stream alc_pcm_null_playback = {
1310 static int alc_build_pcms(struct hda_codec *codec)
1312 struct alc_spec *spec = codec->spec;
1313 struct hda_pcm *info = spec->pcm_rec;
1316 codec->num_pcms = 1;
1317 codec->pcm_info = info;
1319 info->name = spec->stream_name_analog;
1320 if (spec->stream_analog_playback) {
1321 snd_assert(spec->multiout.dac_nids, return -EINVAL);
1322 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1323 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1325 if (spec->stream_analog_capture) {
1326 snd_assert(spec->adc_nids, return -EINVAL);
1327 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1328 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1331 if (spec->channel_mode) {
1332 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1333 for (i = 0; i < spec->num_channel_mode; i++) {
1334 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1335 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1340 /* If the use of more than one ADC is requested for the current
1341 * model, configure a second analog capture-only PCM.
1343 if (spec->num_adc_nids > 1) {
1346 info->name = spec->stream_name_analog;
1347 /* No playback stream for second PCM */
1348 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
1349 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
1350 if (spec->stream_analog_capture) {
1351 snd_assert(spec->adc_nids, return -EINVAL);
1352 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1353 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
1357 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
1360 info->name = spec->stream_name_digital;
1361 if (spec->multiout.dig_out_nid &&
1362 spec->stream_digital_playback) {
1363 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
1364 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
1366 if (spec->dig_in_nid &&
1367 spec->stream_digital_capture) {
1368 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
1369 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
1376 static void alc_free(struct hda_codec *codec)
1378 struct alc_spec *spec = codec->spec;
1384 if (spec->kctl_alloc) {
1385 for (i = 0; i < spec->num_kctl_used; i++)
1386 kfree(spec->kctl_alloc[i].name);
1387 kfree(spec->kctl_alloc);
1394 static struct hda_codec_ops alc_patch_ops = {
1395 .build_controls = alc_build_controls,
1396 .build_pcms = alc_build_pcms,
1400 .resume = alc_resume,
1406 * Test configuration for debugging
1408 * Almost all inputs/outputs are enabled. I/O pins can be configured via
1411 #ifdef CONFIG_SND_DEBUG
1412 static hda_nid_t alc880_test_dac_nids[4] = {
1413 0x02, 0x03, 0x04, 0x05
1416 static struct hda_input_mux alc880_test_capture_source = {
1427 static struct hda_channel_mode alc880_test_modes[4] = {
1434 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1436 static char *texts[] = {
1437 "N/A", "Line Out", "HP Out",
1438 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1440 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1442 uinfo->value.enumerated.items = 8;
1443 if (uinfo->value.enumerated.item >= 8)
1444 uinfo->value.enumerated.item = 7;
1445 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1449 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1451 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1452 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1453 unsigned int pin_ctl, item = 0;
1455 pin_ctl = snd_hda_codec_read(codec, nid, 0,
1456 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1457 if (pin_ctl & AC_PINCTL_OUT_EN) {
1458 if (pin_ctl & AC_PINCTL_HP_EN)
1462 } else if (pin_ctl & AC_PINCTL_IN_EN) {
1463 switch (pin_ctl & AC_PINCTL_VREFEN) {
1464 case AC_PINCTL_VREF_HIZ: item = 3; break;
1465 case AC_PINCTL_VREF_50: item = 4; break;
1466 case AC_PINCTL_VREF_GRD: item = 5; break;
1467 case AC_PINCTL_VREF_80: item = 6; break;
1468 case AC_PINCTL_VREF_100: item = 7; break;
1471 ucontrol->value.enumerated.item[0] = item;
1475 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1477 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1478 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1479 static unsigned int ctls[] = {
1480 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
1481 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
1482 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
1483 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
1484 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
1485 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
1487 unsigned int old_ctl, new_ctl;
1489 old_ctl = snd_hda_codec_read(codec, nid, 0,
1490 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1491 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
1492 if (old_ctl != new_ctl) {
1493 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
1494 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1495 ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
1501 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1503 static char *texts[] = {
1504 "Front", "Surround", "CLFE", "Side"
1506 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1508 uinfo->value.enumerated.items = 4;
1509 if (uinfo->value.enumerated.item >= 4)
1510 uinfo->value.enumerated.item = 3;
1511 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1515 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1517 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1518 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1521 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
1522 ucontrol->value.enumerated.item[0] = sel & 3;
1526 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1528 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1529 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1532 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
1533 if (ucontrol->value.enumerated.item[0] != sel) {
1534 sel = ucontrol->value.enumerated.item[0] & 3;
1535 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
1541 #define PIN_CTL_TEST(xname,nid) { \
1542 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1544 .info = alc_test_pin_ctl_info, \
1545 .get = alc_test_pin_ctl_get, \
1546 .put = alc_test_pin_ctl_put, \
1547 .private_value = nid \
1550 #define PIN_SRC_TEST(xname,nid) { \
1551 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1553 .info = alc_test_pin_src_info, \
1554 .get = alc_test_pin_src_get, \
1555 .put = alc_test_pin_src_put, \
1556 .private_value = nid \
1559 static struct snd_kcontrol_new alc880_test_mixer[] = {
1560 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1561 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1562 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
1563 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1564 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1565 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1566 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
1567 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1568 PIN_CTL_TEST("Front Pin Mode", 0x14),
1569 PIN_CTL_TEST("Surround Pin Mode", 0x15),
1570 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1571 PIN_CTL_TEST("Side Pin Mode", 0x17),
1572 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1573 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1574 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1575 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1576 PIN_SRC_TEST("In-1 Pin Source", 0x18),
1577 PIN_SRC_TEST("In-2 Pin Source", 0x19),
1578 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1579 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1580 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
1581 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
1582 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
1583 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
1584 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
1585 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
1586 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
1587 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
1588 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
1589 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
1591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592 .name = "Channel Mode",
1593 .info = alc_ch_mode_info,
1594 .get = alc_ch_mode_get,
1595 .put = alc_ch_mode_put,
1600 static struct hda_verb alc880_test_init_verbs[] = {
1601 /* Unmute inputs of 0x0c - 0x0f */
1602 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1603 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1604 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1605 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1606 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1607 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1608 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1609 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1610 /* Vol output for 0x0c-0x0f */
1611 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1612 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1613 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1614 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1615 /* Set output pins 0x14-0x17 */
1616 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1617 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1618 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1619 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1620 /* Unmute output pins 0x14-0x17 */
1621 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1622 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1623 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1624 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1625 /* Set input pins 0x18-0x1c */
1626 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1627 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1628 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1629 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1630 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1631 /* Mute input pins 0x18-0x1b */
1632 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1633 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1634 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1635 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1637 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1638 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1639 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1640 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1641 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1642 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1643 /* Analog input/passthru */
1644 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1645 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1646 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1647 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1648 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1656 static struct hda_board_config alc880_cfg_tbl[] = {
1657 /* Back 3 jack, front 2 jack */
1658 { .modelname = "3stack", .config = ALC880_3ST },
1659 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
1660 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
1661 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
1662 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
1663 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
1664 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
1665 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
1666 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
1667 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
1668 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
1669 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
1670 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
1671 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
1672 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
1673 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
1674 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
1675 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
1676 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
1677 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
1678 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
1679 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
1680 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
1681 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
1682 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
1683 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
1684 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
1685 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
1686 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
1687 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
1688 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1689 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1690 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1692 { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
1694 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1695 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
1696 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
1697 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
1699 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1700 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1701 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1702 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1703 /* Clevo m520G NB */
1704 { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO },
1706 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1707 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
1708 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
1709 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
1711 /* Back 5 jack, front 2 jack */
1712 { .modelname = "5stack", .config = ALC880_5ST },
1713 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
1714 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
1715 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
1716 { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
1717 { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
1719 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1720 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1721 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
1722 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
1723 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
1724 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
1725 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
1726 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
1727 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
1728 { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
1729 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
1730 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1731 { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
1732 /* note subvendor = 0 below */
1733 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1735 { .modelname = "w810", .config = ALC880_W810 },
1736 { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
1738 { .modelname = "z71v", .config = ALC880_Z71V },
1739 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1741 { .modelname = "6stack", .config = ALC880_6ST },
1742 { .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
1743 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
1744 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1745 { .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
1747 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
1748 { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
1749 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1750 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1751 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1752 { .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
1753 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
1754 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
1755 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
1756 { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
1758 { .modelname = "asus", .config = ALC880_ASUS },
1759 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
1760 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
1761 { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
1762 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
1763 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
1764 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
1765 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
1766 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
1767 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1768 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1769 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1770 { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
1772 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1773 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
1775 { .modelname = "F1734", .config = ALC880_F1734 },
1776 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1777 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
1779 #ifdef CONFIG_SND_DEBUG
1780 { .modelname = "test", .config = ALC880_TEST },
1782 { .modelname = "auto", .config = ALC880_AUTO },
1788 * ALC880 codec presets
1790 static struct alc_config_preset alc880_presets[] = {
1792 .mixers = { alc880_three_stack_mixer },
1793 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1794 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1795 .dac_nids = alc880_dac_nids,
1796 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1797 .channel_mode = alc880_threestack_modes,
1798 .input_mux = &alc880_capture_source,
1800 [ALC880_3ST_DIG] = {
1801 .mixers = { alc880_three_stack_mixer },
1802 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1803 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1804 .dac_nids = alc880_dac_nids,
1805 .dig_out_nid = ALC880_DIGOUT_NID,
1806 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1807 .channel_mode = alc880_threestack_modes,
1808 .input_mux = &alc880_capture_source,
1810 [ALC880_TCL_S700] = {
1811 .mixers = { alc880_tcl_s700_mixer },
1812 .init_verbs = { alc880_volume_init_verbs,
1813 alc880_pin_tcl_S700_init_verbs,
1814 alc880_gpio2_init_verbs },
1815 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1816 .dac_nids = alc880_dac_nids,
1818 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1819 .channel_mode = alc880_2_jack_modes,
1820 .input_mux = &alc880_capture_source,
1823 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1824 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1825 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1826 .dac_nids = alc880_dac_nids,
1827 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1828 .channel_mode = alc880_fivestack_modes,
1829 .input_mux = &alc880_capture_source,
1831 [ALC880_5ST_DIG] = {
1832 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
1833 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1834 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1835 .dac_nids = alc880_dac_nids,
1836 .dig_out_nid = ALC880_DIGOUT_NID,
1837 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1838 .channel_mode = alc880_fivestack_modes,
1839 .input_mux = &alc880_capture_source,
1842 .mixers = { alc880_six_stack_mixer },
1843 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1844 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1845 .dac_nids = alc880_6st_dac_nids,
1846 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1847 .channel_mode = alc880_sixstack_modes,
1848 .input_mux = &alc880_6stack_capture_source,
1850 [ALC880_6ST_DIG] = {
1851 .mixers = { alc880_six_stack_mixer },
1852 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1853 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1854 .dac_nids = alc880_6st_dac_nids,
1855 .dig_out_nid = ALC880_DIGOUT_NID,
1856 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1857 .channel_mode = alc880_sixstack_modes,
1858 .input_mux = &alc880_6stack_capture_source,
1861 .mixers = { alc880_w810_base_mixer },
1862 .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
1863 alc880_gpio2_init_verbs },
1864 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
1865 .dac_nids = alc880_w810_dac_nids,
1866 .dig_out_nid = ALC880_DIGOUT_NID,
1867 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
1868 .channel_mode = alc880_w810_modes,
1869 .input_mux = &alc880_capture_source,
1872 .mixers = { alc880_z71v_mixer },
1873 .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
1874 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
1875 .dac_nids = alc880_z71v_dac_nids,
1876 .dig_out_nid = ALC880_DIGOUT_NID,
1878 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1879 .channel_mode = alc880_2_jack_modes,
1880 .input_mux = &alc880_capture_source,
1883 .mixers = { alc880_f1734_mixer },
1884 .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
1885 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
1886 .dac_nids = alc880_f1734_dac_nids,
1888 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1889 .channel_mode = alc880_2_jack_modes,
1890 .input_mux = &alc880_capture_source,
1893 .mixers = { alc880_asus_mixer },
1894 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1895 alc880_gpio1_init_verbs },
1896 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1897 .dac_nids = alc880_asus_dac_nids,
1898 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1899 .channel_mode = alc880_asus_modes,
1900 .input_mux = &alc880_capture_source,
1902 [ALC880_ASUS_DIG] = {
1903 .mixers = { alc880_asus_mixer },
1904 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1905 alc880_gpio1_init_verbs },
1906 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1907 .dac_nids = alc880_asus_dac_nids,
1908 .dig_out_nid = ALC880_DIGOUT_NID,
1909 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1910 .channel_mode = alc880_asus_modes,
1911 .input_mux = &alc880_capture_source,
1913 [ALC880_ASUS_DIG2] = {
1914 .mixers = { alc880_asus_mixer },
1915 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1916 alc880_gpio2_init_verbs }, /* use GPIO2 */
1917 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1918 .dac_nids = alc880_asus_dac_nids,
1919 .dig_out_nid = ALC880_DIGOUT_NID,
1920 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1921 .channel_mode = alc880_asus_modes,
1922 .input_mux = &alc880_capture_source,
1924 [ALC880_ASUS_W1V] = {
1925 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
1926 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1927 alc880_gpio1_init_verbs },
1928 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1929 .dac_nids = alc880_asus_dac_nids,
1930 .dig_out_nid = ALC880_DIGOUT_NID,
1931 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1932 .channel_mode = alc880_asus_modes,
1933 .input_mux = &alc880_capture_source,
1935 [ALC880_UNIWILL_DIG] = {
1936 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
1937 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
1938 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1939 .dac_nids = alc880_asus_dac_nids,
1940 .dig_out_nid = ALC880_DIGOUT_NID,
1941 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1942 .channel_mode = alc880_asus_modes,
1943 .input_mux = &alc880_capture_source,
1946 .mixers = { alc880_three_stack_mixer },
1947 .init_verbs = { alc880_volume_init_verbs,
1948 alc880_pin_clevo_init_verbs },
1949 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1950 .dac_nids = alc880_dac_nids,
1952 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1953 .channel_mode = alc880_threestack_modes,
1954 .input_mux = &alc880_capture_source,
1956 #ifdef CONFIG_SND_DEBUG
1958 .mixers = { alc880_test_mixer },
1959 .init_verbs = { alc880_test_init_verbs },
1960 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
1961 .dac_nids = alc880_test_dac_nids,
1962 .dig_out_nid = ALC880_DIGOUT_NID,
1963 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
1964 .channel_mode = alc880_test_modes,
1965 .input_mux = &alc880_test_capture_source,
1971 * Automatic parse of I/O pins from the BIOS configuration
1974 #define NUM_CONTROL_ALLOC 32
1975 #define NUM_VERB_ALLOC 32
1979 ALC_CTL_WIDGET_MUTE,
1982 static struct snd_kcontrol_new alc880_control_templates[] = {
1983 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
1984 HDA_CODEC_MUTE(NULL, 0, 0, 0),
1985 HDA_BIND_MUTE(NULL, 0, 0, 0),
1988 /* add dynamic controls */
1989 static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
1991 struct snd_kcontrol_new *knew;
1993 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
1994 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
1996 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
1999 if (spec->kctl_alloc) {
2000 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
2001 kfree(spec->kctl_alloc);
2003 spec->kctl_alloc = knew;
2004 spec->num_kctl_alloc = num;
2007 knew = &spec->kctl_alloc[spec->num_kctl_used];
2008 *knew = alc880_control_templates[type];
2009 knew->name = kstrdup(name, GFP_KERNEL);
2012 knew->private_value = val;
2013 spec->num_kctl_used++;
2017 #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
2018 #define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
2019 #define alc880_is_multi_pin(nid) ((nid) >= 0x18)
2020 #define alc880_multi_pin_idx(nid) ((nid) - 0x18)
2021 #define alc880_is_input_pin(nid) ((nid) >= 0x18)
2022 #define alc880_input_pin_idx(nid) ((nid) - 0x18)
2023 #define alc880_idx_to_dac(nid) ((nid) + 0x02)
2024 #define alc880_dac_to_idx(nid) ((nid) - 0x02)
2025 #define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
2026 #define alc880_idx_to_selector(nid) ((nid) + 0x10)
2027 #define ALC880_PIN_CD_NID 0x1c
2029 /* fill in the dac_nids table from the parsed pin configuration */
2030 static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
2036 memset(assigned, 0, sizeof(assigned));
2037 spec->multiout.dac_nids = spec->private_dac_nids;
2039 /* check the pins hardwired to audio widget */
2040 for (i = 0; i < cfg->line_outs; i++) {
2041 nid = cfg->line_out_pins[i];
2042 if (alc880_is_fixed_pin(nid)) {
2043 int idx = alc880_fixed_pin_idx(nid);
2044 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
2048 /* left pins can be connect to any audio widget */
2049 for (i = 0; i < cfg->line_outs; i++) {
2050 nid = cfg->line_out_pins[i];
2051 if (alc880_is_fixed_pin(nid))
2053 /* search for an empty channel */
2054 for (j = 0; j < cfg->line_outs; j++) {
2055 if (! assigned[j]) {
2056 spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
2062 spec->multiout.num_dacs = cfg->line_outs;
2066 /* add playback controls from the parsed DAC table */
2067 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
2068 const struct auto_pin_cfg *cfg)
2071 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2075 for (i = 0; i < cfg->line_outs; i++) {
2076 if (! spec->multiout.dac_nids[i])
2078 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
2081 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
2082 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
2084 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
2085 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
2087 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
2088 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
2090 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
2091 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
2094 sprintf(name, "%s Playback Volume", chname[i]);
2095 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2096 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2098 sprintf(name, "%s Playback Switch", chname[i]);
2099 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2100 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2107 /* add playback controls for speaker and HP outputs */
2108 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
2118 if (alc880_is_fixed_pin(pin)) {
2119 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
2120 if (! spec->multiout.dac_nids[0]) {
2121 /* use this as the primary output */
2122 spec->multiout.dac_nids[0] = nid;
2123 if (! spec->multiout.num_dacs)
2124 spec->multiout.num_dacs = 1;
2126 /* specify the DAC as the extra output */
2127 spec->multiout.hp_nid = nid;
2128 /* control HP volume/switch on the output mixer amp */
2129 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
2130 sprintf(name, "%s Playback Volume", pfx);
2131 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2132 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
2134 sprintf(name, "%s Playback Switch", pfx);
2135 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
2136 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2138 } else if (alc880_is_multi_pin(pin)) {
2139 /* set manual connection */
2140 if (! spec->multiout.dac_nids[0]) {
2141 /* use this as the primary output */
2142 spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
2143 if (! spec->multiout.num_dacs)
2144 spec->multiout.num_dacs = 1;
2146 /* we have only a switch on HP-out PIN */
2147 sprintf(name, "%s Playback Switch", pfx);
2148 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2149 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
2155 /* create input playback/capture controls for the given pin */
2156 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
2157 int idx, hda_nid_t mix_nid)
2162 sprintf(name, "%s Playback Volume", ctlname);
2163 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
2164 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2166 sprintf(name, "%s Playback Switch", ctlname);
2167 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
2168 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
2173 /* create playback/capture controls for input pins */
2174 static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
2175 const struct auto_pin_cfg *cfg)
2177 struct hda_input_mux *imux = &spec->private_imux;
2180 for (i = 0; i < AUTO_PIN_LAST; i++) {
2181 if (alc880_is_input_pin(cfg->input_pins[i])) {
2182 idx = alc880_input_pin_idx(cfg->input_pins[i]);
2183 err = new_analog_input(spec, cfg->input_pins[i],
2184 auto_pin_cfg_labels[i],
2188 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2189 imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
2196 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
2197 hda_nid_t nid, int pin_type,
2201 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2202 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2203 /* need the manual connection? */
2204 if (alc880_is_multi_pin(nid)) {
2205 struct alc_spec *spec = codec->spec;
2206 int idx = alc880_multi_pin_idx(nid);
2207 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
2208 AC_VERB_SET_CONNECT_SEL,
2209 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
2213 static void alc880_auto_init_multi_out(struct hda_codec *codec)
2215 struct alc_spec *spec = codec->spec;
2218 for (i = 0; i < spec->autocfg.line_outs; i++) {
2219 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2220 alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2224 static void alc880_auto_init_extra_out(struct hda_codec *codec)
2226 struct alc_spec *spec = codec->spec;
2229 pin = spec->autocfg.speaker_pin;
2230 if (pin) /* connect to front */
2231 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2232 pin = spec->autocfg.hp_pin;
2233 if (pin) /* connect to front */
2234 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2237 static void alc880_auto_init_analog_input(struct hda_codec *codec)
2239 struct alc_spec *spec = codec->spec;
2242 for (i = 0; i < AUTO_PIN_LAST; i++) {
2243 hda_nid_t nid = spec->autocfg.input_pins[i];
2244 if (alc880_is_input_pin(nid)) {
2245 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2246 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2247 if (nid != ALC880_PIN_CD_NID)
2248 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2254 /* parse the BIOS configuration and set up the alc_spec */
2255 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
2256 static int alc880_parse_auto_config(struct hda_codec *codec)
2258 struct alc_spec *spec = codec->spec;
2260 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
2262 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2263 alc880_ignore)) < 0)
2265 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
2266 ! spec->autocfg.hp_pin)
2267 return 0; /* can't find valid BIOS pin config */
2269 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
2270 (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2271 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2273 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
2274 "Headphone")) < 0 ||
2275 (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2278 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2280 if (spec->autocfg.dig_out_pin)
2281 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2282 if (spec->autocfg.dig_in_pin)
2283 spec->dig_in_nid = ALC880_DIGIN_NID;
2285 if (spec->kctl_alloc)
2286 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2288 spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2290 spec->input_mux = &spec->private_imux;
2295 /* init callback for auto-configuration model -- overriding the default init */
2296 static int alc880_auto_init(struct hda_codec *codec)
2299 alc880_auto_init_multi_out(codec);
2300 alc880_auto_init_extra_out(codec);
2301 alc880_auto_init_analog_input(codec);
2306 * OK, here we have finally the patch for ALC880
2309 static int patch_alc880(struct hda_codec *codec)
2311 struct alc_spec *spec;
2315 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2321 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
2322 if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
2323 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2324 board_config = ALC880_AUTO;
2327 if (board_config == ALC880_AUTO) {
2328 /* automatic parse from the BIOS config */
2329 err = alc880_parse_auto_config(codec);
2334 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
2335 board_config = ALC880_3ST;
2339 if (board_config != ALC880_AUTO)
2340 setup_preset(spec, &alc880_presets[board_config]);
2342 spec->stream_name_analog = "ALC880 Analog";
2343 spec->stream_analog_playback = &alc880_pcm_analog_playback;
2344 spec->stream_analog_capture = &alc880_pcm_analog_capture;
2346 spec->stream_name_digital = "ALC880 Digital";
2347 spec->stream_digital_playback = &alc880_pcm_digital_playback;
2348 spec->stream_digital_capture = &alc880_pcm_digital_capture;
2350 if (! spec->adc_nids && spec->input_mux) {
2351 /* check whether NID 0x07 is valid */
2352 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
2353 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2354 if (wcap != AC_WID_AUD_IN) {
2355 spec->adc_nids = alc880_adc_nids_alt;
2356 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
2357 spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
2360 spec->adc_nids = alc880_adc_nids;
2361 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
2362 spec->mixers[spec->num_mixers] = alc880_capture_mixer;
2367 codec->patch_ops = alc_patch_ops;
2368 if (board_config == ALC880_AUTO)
2369 codec->patch_ops.init = alc880_auto_init;
2379 static hda_nid_t alc260_dac_nids[1] = {
2384 static hda_nid_t alc260_adc_nids[1] = {
2389 static hda_nid_t alc260_adc_nids_alt[1] = {
2394 static hda_nid_t alc260_hp_adc_nids[2] = {
2399 static hda_nid_t alc260_fujitsu_adc_nids[2] = {
2404 #define ALC260_DIGOUT_NID 0x03
2405 #define ALC260_DIGIN_NID 0x06
2407 static struct hda_input_mux alc260_capture_source = {
2411 { "Front Mic", 0x1 },
2417 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
2418 * headphone jack and the internal CD lines.
2420 static struct hda_input_mux alc260_fujitsu_capture_source = {
2423 { "Mic/Line", 0x0 },
2425 { "Headphone", 0x2 },
2430 * This is just place-holder, so there's something for alc_build_pcms to look
2431 * at when it calculates the maximum number of channels. ALC260 has no mixer
2432 * element which allows changing the channel mode, so the verb list is
2435 static struct hda_channel_mode alc260_modes[1] = {
2440 /* Mixer combinations
2442 * basic: base_output + input + pc_beep + capture
2443 * HP: base_output + input + capture_alt
2444 * HP_3013: hp_3013 + input + capture
2445 * fujitsu: fujitsu + capture
2448 static struct snd_kcontrol_new alc260_base_output_mixer[] = {
2449 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2450 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2451 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2452 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2453 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2454 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2458 static struct snd_kcontrol_new alc260_input_mixer[] = {
2459 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2460 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2461 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2462 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2464 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2465 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2466 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2470 static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
2471 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2472 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2476 static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
2477 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2478 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2479 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
2480 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
2481 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2482 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
2483 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2484 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
2488 static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2489 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2490 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
2491 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
2492 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2493 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2494 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
2495 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
2496 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
2497 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2498 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2499 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2500 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2504 /* capture mixer elements */
2505 static struct snd_kcontrol_new alc260_capture_mixer[] = {
2506 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2507 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2508 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
2509 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
2511 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2512 /* The multiple "Capture Source" controls confuse alsamixer
2513 * So call somewhat different..
2514 * FIXME: the controls appear in the "playback" view!
2516 /* .name = "Capture Source", */
2517 .name = "Input Source",
2519 .info = alc_mux_enum_info,
2520 .get = alc_mux_enum_get,
2521 .put = alc_mux_enum_put,
2526 static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
2527 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2528 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2531 /* The multiple "Capture Source" controls confuse alsamixer
2532 * So call somewhat different..
2533 * FIXME: the controls appear in the "playback" view!
2535 /* .name = "Capture Source", */
2536 .name = "Input Source",
2538 .info = alc_mux_enum_info,
2539 .get = alc_mux_enum_get,
2540 .put = alc_mux_enum_put,
2546 * initialization verbs
2548 static struct hda_verb alc260_init_verbs[] = {
2549 /* Line In pin widget for input */
2550 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2551 /* CD pin widget for input */
2552 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2553 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2554 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2555 /* Mic2 (front panel) pin widget for input and vref at 80% */
2556 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2557 /* LINE-2 is used for line-out in rear */
2558 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2559 /* select line-out */
2560 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
2562 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2564 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2566 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2567 /* mute capture amp left and right */
2568 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2569 /* set connection select to line in (default select for this ADC) */
2570 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2571 /* mute capture amp left and right */
2572 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2573 /* set connection select to line in (default select for this ADC) */
2574 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
2575 /* set vol=0 Line-Out mixer amp left and right */
2576 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2577 /* unmute pin widget amp left and right (no gain on this amp) */
2578 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2579 /* set vol=0 HP mixer amp left and right */
2580 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2581 /* unmute pin widget amp left and right (no gain on this amp) */
2582 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2583 /* set vol=0 Mono mixer amp left and right */
2584 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2585 /* unmute pin widget amp left and right (no gain on this amp) */
2586 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2587 /* unmute LINE-2 out pin */
2588 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2589 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2591 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2593 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2595 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2596 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2597 /* mute Front out path */
2598 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2599 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2600 /* mute Headphone out path */
2601 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2602 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2603 /* mute Mono out path */
2604 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2605 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2609 static struct hda_verb alc260_hp_init_verbs[] = {
2610 /* Headphone and output */
2611 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2613 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2614 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2615 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2616 /* Mic2 (front panel) pin widget for input and vref at 80% */
2617 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2618 /* Line In pin widget for input */
2619 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2620 /* Line-2 pin widget for output */
2621 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2622 /* CD pin widget for input */
2623 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2624 /* unmute amp left and right */
2625 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2626 /* set connection select to line in (default select for this ADC) */
2627 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2628 /* unmute Line-Out mixer amp left and right (volume = 0) */
2629 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2630 /* mute pin widget amp left and right (no gain on this amp) */
2631 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2632 /* unmute HP mixer amp left and right (volume = 0) */
2633 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2634 /* mute pin widget amp left and right (no gain on this amp) */
2635 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2636 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2638 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2639 /* unmute Line In */
2640 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2642 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2643 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2644 /* Unmute Front out path */
2645 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2646 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2647 /* Unmute Headphone out path */
2648 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2649 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2650 /* Unmute Mono out path */
2651 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2652 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2656 static struct hda_verb alc260_hp_3013_init_verbs[] = {
2657 /* Line out and output */
2658 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2660 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2661 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2662 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2663 /* Mic2 (front panel) pin widget for input and vref at 80% */
2664 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2665 /* Line In pin widget for input */
2666 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2667 /* Headphone pin widget for output */
2668 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2669 /* CD pin widget for input */
2670 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2671 /* unmute amp left and right */
2672 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2673 /* set connection select to line in (default select for this ADC) */
2674 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2675 /* unmute Line-Out mixer amp left and right (volume = 0) */
2676 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2677 /* mute pin widget amp left and right (no gain on this amp) */
2678 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2679 /* unmute HP mixer amp left and right (volume = 0) */
2680 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2681 /* mute pin widget amp left and right (no gain on this amp) */
2682 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2683 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2685 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2686 /* unmute Line In */
2687 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2689 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2690 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2691 /* Unmute Front out path */
2692 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2693 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2694 /* Unmute Headphone out path */
2695 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2696 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2697 /* Unmute Mono out path */
2698 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2699 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2703 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2706 static struct hda_verb alc260_fujitsu_init_verbs[] = {
2707 /* Disable all GPIOs */
2708 {0x01, AC_VERB_SET_GPIO_MASK, 0},
2709 /* Internal speaker is connected to headphone pin */
2710 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2711 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
2712 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2713 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2714 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2715 /* Ensure all other unused pins are disabled and muted.
2716 * Note: trying to set widget 0x15 to anything blocks all audio
2717 * output for some reason, so just leave that at the default.
2719 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2720 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2721 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2722 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2723 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2724 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2725 /* Disable digital (SPDIF) pins */
2726 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2727 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2729 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
2730 * when acting as an output.
2732 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2734 /* Start with output sum widgets muted and their output gains at min */
2735 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2736 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2737 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2738 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2739 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2740 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2741 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2742 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2743 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2745 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2746 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2747 /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
2748 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2749 /* Unmute Line1 pin widget input for when this pin is used as input
2750 * (no equiv mixer ctrl). Having input and output unmuted doesn't
2751 * seem to cause a problem.
2753 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2754 /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
2755 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2757 /* Mute capture amp left and right */
2758 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2759 /* Set ADC connection select to match default mixer setting - line
2762 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2764 /* Do the same for the second ADC: mute capture input amp and
2765 * set ADC connection to line in
2767 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2768 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2770 /* Mute all inputs to mixer widget (even unconnected ones) */
2771 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2772 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2773 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2774 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2775 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2776 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2777 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2778 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2783 /* Test configuration for debugging, modelled after the ALC880 test
2786 #ifdef CONFIG_SND_DEBUG
2787 static hda_nid_t alc260_test_dac_nids[1] = {
2790 static hda_nid_t alc260_test_adc_nids[2] = {
2793 /* This is a bit messy since the two input muxes in the ALC260 have slight
2794 * variations in their signal assignments. The ideal way to deal with this
2795 * is to extend alc_spec.input_mux to allow a different input MUX for each
2796 * ADC. For the purposes of the test model it's sufficient to just list
2797 * both options for affected signal indices. The separate input mux
2798 * functionality only needs to be considered if a model comes along which
2799 * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
2802 static struct hda_input_mux alc260_test_capture_source = {
2805 { "MIC1 pin", 0x0 },
2806 { "MIC2 pin", 0x1 },
2807 { "LINE1 pin", 0x2 },
2808 { "LINE2 pin", 0x3 },
2810 { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
2811 { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
2812 { "HP-OUT pin (cap2 only)", 0x7 },
2815 static struct snd_kcontrol_new alc260_test_mixer[] = {
2816 /* Output driver widgets */
2817 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2818 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2819 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2820 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
2821 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2822 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
2824 /* Modes for retasking pin widgets */
2825 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
2826 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
2827 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
2828 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
2829 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
2830 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
2832 /* Loopback mixer controls */
2833 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
2834 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
2835 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
2836 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
2837 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
2838 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
2839 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
2840 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
2841 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2842 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2843 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2844 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2845 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
2846 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
2847 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
2848 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
2851 static struct hda_verb alc260_test_init_verbs[] = {
2852 /* Disable all GPIOs */
2853 {0x01, AC_VERB_SET_GPIO_MASK, 0},
2854 /* Enable retasking pins as output, initially without power amp */
2855 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2856 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2857 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2858 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2859 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2860 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2862 /* Disable digital (SPDIF) pins for now */
2863 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2864 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2866 /* Ensure mic1, mic2, line1 and line2 pin widget take input from the
2867 * OUT1 sum bus when acting as an output.
2869 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
2870 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
2871 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2872 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
2874 /* Start with output sum widgets muted and their output gains at min */
2875 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2876 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2877 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2878 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2879 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2880 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2881 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2882 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2883 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2885 /* Unmute retasking pin widget output amp left/right (no mixer ctrl) */
2886 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2887 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2888 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2889 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2890 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2891 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2892 /* Also unmute the mono-out pin widget */
2893 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2895 /* Also unmute the retasking pin input amps. Having the input and
2896 * output amps unmuted at the same time doesn't appear to cause any
2899 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2900 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2901 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2902 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2903 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2904 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2906 /* Mute capture amp left and right */
2907 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2908 /* Set ADC connection select to match default mixer setting - line
2911 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2913 /* Do the same for the second ADC: mute capture input amp and
2914 * set ADC connection to line in
2916 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2917 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2919 /* Mute all inputs to mixer widget (even unconnected ones) */
2920 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2921 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2922 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2923 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2924 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2925 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2926 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2927 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2933 static struct hda_pcm_stream alc260_pcm_analog_playback = {
2939 static struct hda_pcm_stream alc260_pcm_analog_capture = {
2945 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
2946 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
2949 * for BIOS auto-configuration
2952 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
2956 unsigned long vol_val, sw_val;
2960 if (nid >= 0x0f && nid < 0x11) {
2961 nid_vol = nid - 0x7;
2962 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2963 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2964 } else if (nid == 0x11) {
2965 nid_vol = nid - 0x7;
2966 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
2967 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
2968 } else if (nid >= 0x12 && nid <= 0x15) {
2970 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2971 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2975 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
2976 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
2978 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
2979 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
2984 /* add playback controls from the parsed DAC table */
2985 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
2986 const struct auto_pin_cfg *cfg)
2991 spec->multiout.num_dacs = 1;
2992 spec->multiout.dac_nids = spec->private_dac_nids;
2993 spec->multiout.dac_nids[0] = 0x02;
2995 nid = cfg->line_out_pins[0];
2997 err = alc260_add_playback_controls(spec, nid, "Front");
3002 nid = cfg->speaker_pin;
3004 err = alc260_add_playback_controls(spec, nid, "Speaker");
3011 err = alc260_add_playback_controls(spec, nid, "Headphone");
3018 /* create playback/capture controls for input pins */
3019 static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
3020 const struct auto_pin_cfg *cfg)
3022 struct hda_input_mux *imux = &spec->private_imux;
3025 for (i = 0; i < AUTO_PIN_LAST; i++) {
3026 if (cfg->input_pins[i] >= 0x12) {
3027 idx = cfg->input_pins[i] - 0x12;
3028 err = new_analog_input(spec, cfg->input_pins[i],
3029 auto_pin_cfg_labels[i], idx, 0x07);
3032 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3033 imux->items[imux->num_items].index = idx;
3036 if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
3037 idx = cfg->input_pins[i] - 0x09;
3038 err = new_analog_input(spec, cfg->input_pins[i],
3039 auto_pin_cfg_labels[i], idx, 0x07);
3042 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3043 imux->items[imux->num_items].index = idx;
3050 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3051 hda_nid_t nid, int pin_type,
3055 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3056 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3057 /* need the manual connection? */
3059 int idx = nid - 0x12;
3060 snd_hda_codec_write(codec, idx + 0x0b, 0,
3061 AC_VERB_SET_CONNECT_SEL, sel_idx);
3066 static void alc260_auto_init_multi_out(struct hda_codec *codec)
3068 struct alc_spec *spec = codec->spec;
3071 nid = spec->autocfg.line_out_pins[0];
3073 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3075 nid = spec->autocfg.speaker_pin;
3077 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3079 nid = spec->autocfg.hp_pin;
3081 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3084 #define ALC260_PIN_CD_NID 0x16
3085 static void alc260_auto_init_analog_input(struct hda_codec *codec)
3087 struct alc_spec *spec = codec->spec;
3090 for (i = 0; i < AUTO_PIN_LAST; i++) {
3091 hda_nid_t nid = spec->autocfg.input_pins[i];
3093 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3094 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3095 if (nid != ALC260_PIN_CD_NID)
3096 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3103 * generic initialization of ADC, input mixers and output mixers
3105 static struct hda_verb alc260_volume_init_verbs[] = {
3107 * Unmute ADC0-1 and set the default input to mic-in
3109 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3110 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3111 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3112 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3114 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3116 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3119 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3120 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3121 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3122 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3123 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3124 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3127 * Set up output mixers (0x08 - 0x0a)
3129 /* set vol=0 to output mixers */
3130 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3131 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3132 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3133 /* set up input amps for analog loopback */
3134 /* Amp Indices: DAC = 0, mixer = 1 */
3135 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3136 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3137 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3138 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3139 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3140 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3145 static int alc260_parse_auto_config(struct hda_codec *codec)
3147 struct alc_spec *spec = codec->spec;
3150 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
3152 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3153 alc260_ignore)) < 0)
3155 if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
3157 if (! spec->kctl_alloc)
3158 return 0; /* can't find valid BIOS pin config */
3159 if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3162 spec->multiout.max_channels = 2;
3164 if (spec->autocfg.dig_out_pin)
3165 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
3166 if (spec->kctl_alloc)
3167 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3169 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
3171 spec->input_mux = &spec->private_imux;
3173 /* check whether NID 0x04 is valid */
3174 wcap = get_wcaps(codec, 0x04);
3175 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3176 if (wcap != AC_WID_AUD_IN) {
3177 spec->adc_nids = alc260_adc_nids_alt;
3178 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
3179 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
3181 spec->adc_nids = alc260_adc_nids;
3182 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
3183 spec->mixers[spec->num_mixers] = alc260_capture_mixer;
3190 /* init callback for auto-configuration model -- overriding the default init */
3191 static int alc260_auto_init(struct hda_codec *codec)
3194 alc260_auto_init_multi_out(codec);
3195 alc260_auto_init_analog_input(codec);
3200 * ALC260 configurations
3202 static struct hda_board_config alc260_cfg_tbl[] = {
3203 { .modelname = "basic", .config = ALC260_BASIC },
3204 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
3205 .config = ALC260_BASIC }, /* Sony VAIO */
3206 { .modelname = "hp", .config = ALC260_HP },
3207 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
3208 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3209 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
3210 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3211 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3212 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
3213 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
3214 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
3215 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
3216 #ifdef CONFIG_SND_DEBUG
3217 { .modelname = "test", .config = ALC260_TEST },
3219 { .modelname = "auto", .config = ALC260_AUTO },
3223 static struct alc_config_preset alc260_presets[] = {
3225 .mixers = { alc260_base_output_mixer,
3227 alc260_pc_beep_mixer,
3228 alc260_capture_mixer },
3229 .init_verbs = { alc260_init_verbs },
3230 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3231 .dac_nids = alc260_dac_nids,
3232 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
3233 .adc_nids = alc260_adc_nids,
3234 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3235 .channel_mode = alc260_modes,
3236 .input_mux = &alc260_capture_source,
3239 .mixers = { alc260_base_output_mixer,
3241 alc260_capture_alt_mixer },
3242 .init_verbs = { alc260_hp_init_verbs },
3243 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3244 .dac_nids = alc260_dac_nids,
3245 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3246 .adc_nids = alc260_hp_adc_nids,
3247 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3248 .channel_mode = alc260_modes,
3249 .input_mux = &alc260_capture_source,
3251 [ALC260_HP_3013] = {
3252 .mixers = { alc260_hp_3013_mixer,
3254 alc260_capture_alt_mixer },
3255 .init_verbs = { alc260_hp_3013_init_verbs },
3256 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3257 .dac_nids = alc260_dac_nids,
3258 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3259 .adc_nids = alc260_hp_adc_nids,
3260 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3261 .channel_mode = alc260_modes,
3262 .input_mux = &alc260_capture_source,
3264 [ALC260_FUJITSU_S702X] = {
3265 .mixers = { alc260_fujitsu_mixer,
3266 alc260_capture_mixer },
3267 .init_verbs = { alc260_fujitsu_init_verbs },
3268 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3269 .dac_nids = alc260_dac_nids,
3270 .num_adc_nids = ARRAY_SIZE(alc260_fujitsu_adc_nids),
3271 .adc_nids = alc260_fujitsu_adc_nids,
3272 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3273 .channel_mode = alc260_modes,
3274 .input_mux = &alc260_fujitsu_capture_source,
3276 #ifdef CONFIG_SND_DEBUG
3278 .mixers = { alc260_test_mixer,
3279 alc260_capture_mixer },
3280 .init_verbs = { alc260_test_init_verbs },
3281 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
3282 .dac_nids = alc260_test_dac_nids,
3283 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
3284 .adc_nids = alc260_test_adc_nids,
3285 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3286 .channel_mode = alc260_modes,
3287 .input_mux = &alc260_test_capture_source,
3292 static int patch_alc260(struct hda_codec *codec)
3294 struct alc_spec *spec;
3295 int err, board_config;
3297 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3303 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
3304 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
3305 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
3306 board_config = ALC260_AUTO;
3309 if (board_config == ALC260_AUTO) {
3310 /* automatic parse from the BIOS config */
3311 err = alc260_parse_auto_config(codec);
3316 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3317 board_config = ALC260_BASIC;
3321 if (board_config != ALC260_AUTO)
3322 setup_preset(spec, &alc260_presets[board_config]);
3324 spec->stream_name_analog = "ALC260 Analog";
3325 spec->stream_analog_playback = &alc260_pcm_analog_playback;
3326 spec->stream_analog_capture = &alc260_pcm_analog_capture;
3328 spec->stream_name_digital = "ALC260 Digital";
3329 spec->stream_digital_playback = &alc260_pcm_digital_playback;
3330 spec->stream_digital_capture = &alc260_pcm_digital_capture;
3332 codec->patch_ops = alc_patch_ops;
3333 if (board_config == ALC260_AUTO)
3334 codec->patch_ops.init = alc260_auto_init;
3343 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3344 * configuration. Each pin widget can choose any input DACs and a mixer.
3345 * Each ADC is connected from a mixer of all inputs. This makes possible
3346 * 6-channel independent captures.
3348 * In addition, an independent DAC for the multi-playback (not used in this
3351 #define ALC882_DIGOUT_NID 0x06
3352 #define ALC882_DIGIN_NID 0x0a
3354 static struct hda_channel_mode alc882_ch_modes[1] = {
3358 static hda_nid_t alc882_dac_nids[4] = {
3359 /* front, rear, clfe, rear_surr */
3360 0x02, 0x03, 0x04, 0x05
3363 /* identical with ALC880 */
3364 #define alc882_adc_nids alc880_adc_nids
3365 #define alc882_adc_nids_alt alc880_adc_nids_alt
3368 /* FIXME: should be a matrix-type input source selection */
3370 static struct hda_input_mux alc882_capture_source = {
3374 { "Front Mic", 0x1 },
3380 #define alc882_mux_enum_info alc_mux_enum_info
3381 #define alc882_mux_enum_get alc_mux_enum_get
3383 static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3385 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3386 struct alc_spec *spec = codec->spec;
3387 const struct hda_input_mux *imux = spec->input_mux;
3388 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3389 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
3390 hda_nid_t nid = capture_mixers[adc_idx];
3391 unsigned int *cur_val = &spec->cur_mux[adc_idx];
3392 unsigned int i, idx;
3394 idx = ucontrol->value.enumerated.item[0];
3395 if (idx >= imux->num_items)
3396 idx = imux->num_items - 1;
3397 if (*cur_val == idx && ! codec->in_resume)
3399 for (i = 0; i < imux->num_items; i++) {
3400 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
3401 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3402 v | (imux->items[i].index << 8));
3411 static struct hda_verb alc882_sixstack_ch6_init[] = {
3412 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
3413 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3414 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3415 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3422 static struct hda_verb alc882_sixstack_ch8_init[] = {
3423 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3424 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3425 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3426 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3430 static struct hda_channel_mode alc882_sixstack_modes[2] = {
3431 { 6, alc882_sixstack_ch6_init },
3432 { 8, alc882_sixstack_ch8_init },
3435 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3436 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3438 static struct snd_kcontrol_new alc882_base_mixer[] = {
3439 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3440 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3441 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3442 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3443 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3444 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3445 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3446 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3447 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3448 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
3449 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3450 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3451 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3452 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3453 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3454 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3455 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3456 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3457 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3458 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
3459 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
3460 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3461 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3462 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3463 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3464 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3465 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3467 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3468 /* .name = "Capture Source", */
3469 .name = "Input Source",
3471 .info = alc882_mux_enum_info,
3472 .get = alc882_mux_enum_get,
3473 .put = alc882_mux_enum_put,
3478 static struct snd_kcontrol_new alc882_chmode_mixer[] = {
3480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3481 .name = "Channel Mode",
3482 .info = alc_ch_mode_info,
3483 .get = alc_ch_mode_get,
3484 .put = alc_ch_mode_put,
3489 static struct hda_verb alc882_init_verbs[] = {
3490 /* Front mixer: unmute input/output amp left and right (volume = 0) */
3491 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3492 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3493 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3495 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3496 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3497 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3499 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3500 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3501 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3503 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3504 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3505 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3507 /* Front Pin: output 0 (0x0c) */
3508 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3509 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3510 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3511 /* Rear Pin: output 1 (0x0d) */
3512 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3513 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3514 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3515 /* CLFE Pin: output 2 (0x0e) */
3516 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3517 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3518 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
3519 /* Side Pin: output 3 (0x0f) */
3520 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3521 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3522 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
3523 /* Mic (rear) pin: input vref at 80% */
3524 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3525 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3526 /* Front Mic pin: input vref at 80% */
3527 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3528 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3529 /* Line In pin: input */
3530 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3531 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3532 /* Line-2 In: Headphone output (output 0 - 0x0c) */
3533 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3534 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3535 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3536 /* CD pin widget for input */
3537 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3539 /* FIXME: use matrix-type input source selection */
3540 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3541 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3542 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3544 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3545 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3547 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3548 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3549 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3550 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3552 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3553 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3554 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3555 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3556 /* ADC1: mute amp left and right */
3557 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3558 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3559 /* ADC2: mute amp left and right */
3560 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3561 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3562 /* ADC3: mute amp left and right */
3563 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3564 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3570 * generic initialization of ADC, input mixers and output mixers
3572 static struct hda_verb alc882_auto_init_verbs[] = {
3574 * Unmute ADC0-2 and set the default input to mic-in
3576 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3577 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3578 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3579 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3580 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3581 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3583 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3585 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3588 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3589 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3590 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3591 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3592 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3593 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3596 * Set up output mixers (0x0c - 0x0f)
3598 /* set vol=0 to output mixers */
3599 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3600 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3601 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3602 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3603 /* set up input amps for analog loopback */
3604 /* Amp Indices: DAC = 0, mixer = 1 */
3605 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3606 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3607 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3608 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3609 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3610 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3611 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3612 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3613 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3614 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3616 /* FIXME: use matrix-type input source selection */
3617 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3618 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3619 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3620 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3621 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3622 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3624 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3625 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3626 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3627 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3629 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3630 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3631 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3632 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3637 /* capture mixer elements */
3638 static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
3639 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3640 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3641 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
3642 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
3644 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3645 /* The multiple "Capture Source" controls confuse alsamixer
3646 * So call somewhat different..
3647 * FIXME: the controls appear in the "playback" view!
3649 /* .name = "Capture Source", */
3650 .name = "Input Source",
3652 .info = alc882_mux_enum_info,
3653 .get = alc882_mux_enum_get,
3654 .put = alc882_mux_enum_put,
3659 static struct snd_kcontrol_new alc882_capture_mixer[] = {
3660 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3661 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3662 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3663 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3664 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3665 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3668 /* The multiple "Capture Source" controls confuse alsamixer
3669 * So call somewhat different..
3670 * FIXME: the controls appear in the "playback" view!
3672 /* .name = "Capture Source", */
3673 .name = "Input Source",
3675 .info = alc882_mux_enum_info,
3676 .get = alc882_mux_enum_get,
3677 .put = alc882_mux_enum_put,
3682 /* pcm configuration: identiacal with ALC880 */
3683 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
3684 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
3685 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
3686 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
3689 * configuration and preset
3691 static struct hda_board_config alc882_cfg_tbl[] = {
3692 { .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
3693 { .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
3694 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */
3695 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
3696 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
3697 { .modelname = "auto", .config = ALC882_AUTO },
3701 static struct alc_config_preset alc882_presets[] = {
3702 [ALC882_3ST_DIG] = {
3703 .mixers = { alc882_base_mixer },
3704 .init_verbs = { alc882_init_verbs },
3705 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3706 .dac_nids = alc882_dac_nids,
3707 .dig_out_nid = ALC882_DIGOUT_NID,
3708 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3709 .adc_nids = alc882_adc_nids,
3710 .dig_in_nid = ALC882_DIGIN_NID,
3711 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
3712 .channel_mode = alc882_ch_modes,
3713 .input_mux = &alc882_capture_source,
3715 [ALC882_6ST_DIG] = {
3716 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
3717 .init_verbs = { alc882_init_verbs },
3718 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3719 .dac_nids = alc882_dac_nids,
3720 .dig_out_nid = ALC882_DIGOUT_NID,
3721 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3722 .adc_nids = alc882_adc_nids,
3723 .dig_in_nid = ALC882_DIGIN_NID,
3724 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
3725 .channel_mode = alc882_sixstack_modes,
3726 .input_mux = &alc882_capture_source,
3732 * BIOS auto configuration
3734 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
3735 hda_nid_t nid, int pin_type,
3739 struct alc_spec *spec = codec->spec;
3742 if (spec->multiout.dac_nids[dac_idx] == 0x25)
3745 idx = spec->multiout.dac_nids[dac_idx] - 2;
3747 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3748 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3749 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
3753 static void alc882_auto_init_multi_out(struct hda_codec *codec)
3755 struct alc_spec *spec = codec->spec;
3758 for (i = 0; i <= HDA_SIDE; i++) {
3759 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3761 alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3765 static void alc882_auto_init_hp_out(struct hda_codec *codec)
3767 struct alc_spec *spec = codec->spec;
3770 pin = spec->autocfg.hp_pin;
3771 if (pin) /* connect to front */
3772 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
3775 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
3776 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
3778 static void alc882_auto_init_analog_input(struct hda_codec *codec)
3780 struct alc_spec *spec = codec->spec;
3783 for (i = 0; i < AUTO_PIN_LAST; i++) {
3784 hda_nid_t nid = spec->autocfg.input_pins[i];
3785 if (alc882_is_input_pin(nid)) {
3786 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3787 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3788 if (nid != ALC882_PIN_CD_NID)
3789 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3795 /* almost identical with ALC880 parser... */
3796 static int alc882_parse_auto_config(struct hda_codec *codec)
3798 struct alc_spec *spec = codec->spec;
3799 int err = alc880_parse_auto_config(codec);
3804 /* hack - override the init verbs */
3805 spec->init_verbs[0] = alc882_auto_init_verbs;
3809 /* init callback for auto-configuration model -- overriding the default init */
3810 static int alc882_auto_init(struct hda_codec *codec)
3813 alc882_auto_init_multi_out(codec);
3814 alc882_auto_init_hp_out(codec);
3815 alc882_auto_init_analog_input(codec);
3820 * ALC882 Headphone poll in 3.5.1a or 3.5.2
3823 static int patch_alc882(struct hda_codec *codec)
3825 struct alc_spec *spec;
3826 int err, board_config;
3828 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3834 board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
3836 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
3837 printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
3838 board_config = ALC882_AUTO;
3841 if (board_config == ALC882_AUTO) {
3842 /* automatic parse from the BIOS config */
3843 err = alc882_parse_auto_config(codec);
3848 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3849 board_config = ALC882_3ST_DIG;
3853 if (board_config != ALC882_AUTO)
3854 setup_preset(spec, &alc882_presets[board_config]);
3856 spec->stream_name_analog = "ALC882 Analog";
3857 spec->stream_analog_playback = &alc882_pcm_analog_playback;
3858 spec->stream_analog_capture = &alc882_pcm_analog_capture;
3860 spec->stream_name_digital = "ALC882 Digital";
3861 spec->stream_digital_playback = &alc882_pcm_digital_playback;
3862 spec->stream_digital_capture = &alc882_pcm_digital_capture;
3864 if (! spec->adc_nids && spec->input_mux) {
3865 /* check whether NID 0x07 is valid */
3866 unsigned int wcap = get_wcaps(codec, 0x07);
3867 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3868 if (wcap != AC_WID_AUD_IN) {
3869 spec->adc_nids = alc882_adc_nids_alt;
3870 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
3871 spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
3874 spec->adc_nids = alc882_adc_nids;
3875 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
3876 spec->mixers[spec->num_mixers] = alc882_capture_mixer;
3881 codec->patch_ops = alc_patch_ops;
3882 if (board_config == ALC882_AUTO)
3883 codec->patch_ops.init = alc882_auto_init;
3892 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
3893 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
3895 #define alc262_dac_nids alc260_dac_nids
3896 #define alc262_adc_nids alc882_adc_nids
3897 #define alc262_adc_nids_alt alc882_adc_nids_alt
3899 #define alc262_modes alc260_modes
3900 #define alc262_capture_source alc882_capture_source
3902 static struct snd_kcontrol_new alc262_base_mixer[] = {
3903 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3904 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3905 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3906 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3907 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3908 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3909 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3910 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3911 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3912 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
3913 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3914 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3915 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
3916 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3917 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3918 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
3919 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3920 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3922 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3923 .name = "Capture Source",
3925 .info = alc882_mux_enum_info,
3926 .get = alc882_mux_enum_get,
3927 .put = alc882_mux_enum_put,
3932 #define alc262_capture_mixer alc882_capture_mixer
3933 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
3936 * generic initialization of ADC, input mixers and output mixers
3938 static struct hda_verb alc262_init_verbs[] = {
3940 * Unmute ADC0-2 and set the default input to mic-in
3942 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3943 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3944 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3945 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3946 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3947 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3949 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3951 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3954 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3955 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3956 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3957 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3958 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3959 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3962 * Set up output mixers (0x0c - 0x0e)
3964 /* set vol=0 to output mixers */
3965 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3966 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3967 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3968 /* set up input amps for analog loopback */
3969 /* Amp Indices: DAC = 0, mixer = 1 */
3970 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3971 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3972 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3973 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3974 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3975 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3977 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3978 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3979 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3980 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3981 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3982 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3984 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3985 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3986 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3987 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3988 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3990 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3991 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3993 /* FIXME: use matrix-type input source selection */
3994 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3995 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3996 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3997 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3998 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3999 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4001 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4002 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4003 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4004 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4006 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4007 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4008 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4009 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4014 /* add playback controls from the parsed DAC table */
4015 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4020 spec->multiout.num_dacs = 1; /* only use one dac */
4021 spec->multiout.dac_nids = spec->private_dac_nids;
4022 spec->multiout.dac_nids[0] = 2;
4024 nid = cfg->line_out_pins[0];
4026 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
4027 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4029 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
4030 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4034 nid = cfg->speaker_pin;
4037 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4038 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4040 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4041 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4044 if (! cfg->line_out_pins[0])
4045 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4046 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4048 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4049 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4055 /* spec->multiout.hp_nid = 2; */
4057 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4058 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4060 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4061 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4064 if (! cfg->line_out_pins[0])
4065 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4066 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4068 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4069 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4076 /* identical with ALC880 */
4077 #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
4080 * generic initialization of ADC, input mixers and output mixers
4082 static struct hda_verb alc262_volume_init_verbs[] = {
4084 * Unmute ADC0-2 and set the default input to mic-in
4086 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4087 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4088 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4089 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4090 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4091 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4093 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4095 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4098 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4099 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4100 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4101 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4102 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4103 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4106 * Set up output mixers (0x0c - 0x0f)
4108 /* set vol=0 to output mixers */
4109 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4110 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4111 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4113 /* set up input amps for analog loopback */
4114 /* Amp Indices: DAC = 0, mixer = 1 */
4115 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4116 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4117 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4118 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4119 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4120 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4122 /* FIXME: use matrix-type input source selection */
4123 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4124 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4125 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4126 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4127 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4128 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4130 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4131 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4132 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4133 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4135 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4136 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4137 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4138 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4143 /* pcm configuration: identiacal with ALC880 */
4144 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
4145 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
4146 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
4147 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
4150 * BIOS auto configuration
4152 static int alc262_parse_auto_config(struct hda_codec *codec)
4154 struct alc_spec *spec = codec->spec;
4156 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
4158 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4159 alc262_ignore)) < 0)
4161 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4162 ! spec->autocfg.hp_pin)
4163 return 0; /* can't find valid BIOS pin config */
4164 if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4165 (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4168 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4170 if (spec->autocfg.dig_out_pin)
4171 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
4172 if (spec->autocfg.dig_in_pin)
4173 spec->dig_in_nid = ALC262_DIGIN_NID;
4175 if (spec->kctl_alloc)
4176 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4178 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
4179 spec->input_mux = &spec->private_imux;
4184 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
4185 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
4186 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
4189 /* init callback for auto-configuration model -- overriding the default init */
4190 static int alc262_auto_init(struct hda_codec *codec)
4193 alc262_auto_init_multi_out(codec);
4194 alc262_auto_init_hp_out(codec);
4195 alc262_auto_init_analog_input(codec);
4200 * configuration and preset
4202 static struct hda_board_config alc262_cfg_tbl[] = {
4203 { .modelname = "basic", .config = ALC262_BASIC },
4204 { .modelname = "auto", .config = ALC262_AUTO },
4208 static struct alc_config_preset alc262_presets[] = {
4210 .mixers = { alc262_base_mixer },
4211 .init_verbs = { alc262_init_verbs },
4212 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
4213 .dac_nids = alc262_dac_nids,
4215 .num_channel_mode = ARRAY_SIZE(alc262_modes),
4216 .channel_mode = alc262_modes,
4217 .input_mux = &alc262_capture_source,
4221 static int patch_alc262(struct hda_codec *codec)
4223 struct alc_spec *spec;
4227 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4233 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
4236 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4237 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4238 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4239 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4243 board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
4244 if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
4245 printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4246 board_config = ALC262_AUTO;
4249 if (board_config == ALC262_AUTO) {
4250 /* automatic parse from the BIOS config */
4251 err = alc262_parse_auto_config(codec);
4256 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4257 board_config = ALC262_BASIC;
4261 if (board_config != ALC262_AUTO)
4262 setup_preset(spec, &alc262_presets[board_config]);
4264 spec->stream_name_analog = "ALC262 Analog";
4265 spec->stream_analog_playback = &alc262_pcm_analog_playback;
4266 spec->stream_analog_capture = &alc262_pcm_analog_capture;
4268 spec->stream_name_digital = "ALC262 Digital";
4269 spec->stream_digital_playback = &alc262_pcm_digital_playback;
4270 spec->stream_digital_capture = &alc262_pcm_digital_capture;
4272 if (! spec->adc_nids && spec->input_mux) {
4273 /* check whether NID 0x07 is valid */
4274 unsigned int wcap = get_wcaps(codec, 0x07);
4276 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4277 if (wcap != AC_WID_AUD_IN) {
4278 spec->adc_nids = alc262_adc_nids_alt;
4279 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
4280 spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
4283 spec->adc_nids = alc262_adc_nids;
4284 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
4285 spec->mixers[spec->num_mixers] = alc262_capture_mixer;
4290 codec->patch_ops = alc_patch_ops;
4291 if (board_config == ALC262_AUTO)
4292 codec->patch_ops.init = alc262_auto_init;
4299 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4303 * set the path ways for 2 channel output
4304 * need to set the codec line out and mic 1 pin widgets to inputs
4306 static struct hda_verb alc861_threestack_ch2_init[] = {
4307 /* set pin widget 1Ah (line in) for input */
4308 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4309 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4310 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4312 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
4313 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
4314 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
4319 * need to set the codec line out and mic 1 pin widgets to outputs
4321 static struct hda_verb alc861_threestack_ch6_init[] = {
4322 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4323 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4324 /* set pin widget 18h (mic1) for output (CLFE)*/
4325 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4327 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
4328 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
4330 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
4331 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
4332 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
4336 static struct hda_channel_mode alc861_threestack_modes[2] = {
4337 { 2, alc861_threestack_ch2_init },
4338 { 6, alc861_threestack_ch6_init },
4343 static struct snd_kcontrol_new alc861_base_mixer[] = {
4344 /* output mixer control */
4345 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4346 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4347 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4348 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4349 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
4351 /*Input mixer control */
4352 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4353 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4354 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4355 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4356 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4357 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4358 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4359 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4360 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4361 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4363 /* Capture mixer control */
4364 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4365 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4367 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4368 .name = "Capture Source",
4370 .info = alc_mux_enum_info,
4371 .get = alc_mux_enum_get,
4372 .put = alc_mux_enum_put,
4377 static struct snd_kcontrol_new alc861_3ST_mixer[] = {
4378 /* output mixer control */
4379 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4380 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4381 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4382 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4383 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4385 /* Input mixer control */
4386 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4387 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4388 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4389 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4390 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4391 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4392 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4393 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4394 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4395 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4397 /* Capture mixer control */
4398 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4399 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4402 .name = "Capture Source",
4404 .info = alc_mux_enum_info,
4405 .get = alc_mux_enum_get,
4406 .put = alc_mux_enum_put,
4409 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4410 .name = "Channel Mode",
4411 .info = alc_ch_mode_info,
4412 .get = alc_ch_mode_get,
4413 .put = alc_ch_mode_put,
4414 .private_value = ARRAY_SIZE(alc861_threestack_modes),
4420 * generic initialization of ADC, input mixers and output mixers
4422 static struct hda_verb alc861_base_init_verbs[] = {
4424 * Unmute ADC0 and set the default input to mic-in
4426 /* port-A for surround (rear panel) */
4427 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4428 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
4429 /* port-B for mic-in (rear panel) with vref */
4430 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4431 /* port-C for line-in (rear panel) */
4432 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4433 /* port-D for Front */
4434 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4435 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4436 /* port-E for HP out (front panel) */
4437 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4438 /* route front PCM to HP */
4439 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4440 /* port-F for mic-in (front panel) with vref */
4441 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4442 /* port-G for CLFE (rear panel) */
4443 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4444 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
4445 /* port-H for side (rear panel) */
4446 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4447 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
4449 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4450 /* route front mic to ADC1*/
4451 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4452 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4454 /* Unmute DAC0~3 & spdif out*/
4455 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4456 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4457 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4458 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4459 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4461 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4462 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4463 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4464 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4465 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4467 /* Unmute Stereo Mixer 15 */
4468 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4469 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4470 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4471 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4473 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4474 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4475 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4476 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4477 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4478 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4479 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4480 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4481 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4482 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4487 static struct hda_verb alc861_threestack_init_verbs[] = {
4489 * Unmute ADC0 and set the default input to mic-in
4491 /* port-A for surround (rear panel) */
4492 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4493 /* port-B for mic-in (rear panel) with vref */
4494 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4495 /* port-C for line-in (rear panel) */
4496 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4497 /* port-D for Front */
4498 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4499 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4500 /* port-E for HP out (front panel) */
4501 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4502 /* route front PCM to HP */
4503 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4504 /* port-F for mic-in (front panel) with vref */
4505 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4506 /* port-G for CLFE (rear panel) */
4507 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4508 /* port-H for side (rear panel) */
4509 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4511 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4512 /* route front mic to ADC1*/
4513 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4514 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4515 /* Unmute DAC0~3 & spdif out*/
4516 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4517 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4518 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4519 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4520 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4522 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4523 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4524 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4525 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4526 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4528 /* Unmute Stereo Mixer 15 */
4529 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4530 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4531 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4532 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4534 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4535 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4536 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4537 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4538 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4539 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4540 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4541 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4542 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4543 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4547 * generic initialization of ADC, input mixers and output mixers
4549 static struct hda_verb alc861_auto_init_verbs[] = {
4551 * Unmute ADC0 and set the default input to mic-in
4553 // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4554 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4556 /* Unmute DAC0~3 & spdif out*/
4557 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4558 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4559 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4560 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4561 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4563 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4564 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4565 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4566 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4567 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4569 /* Unmute Stereo Mixer 15 */
4570 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4571 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4572 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4573 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
4575 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4576 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4577 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4578 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4579 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4580 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4581 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4582 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4584 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4585 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4586 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4587 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4588 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4589 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4590 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4591 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4593 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1
4598 /* pcm configuration: identiacal with ALC880 */
4599 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
4600 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
4601 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
4602 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
4605 #define ALC861_DIGOUT_NID 0x07
4607 static struct hda_channel_mode alc861_8ch_modes[1] = {
4611 static hda_nid_t alc861_dac_nids[4] = {
4612 /* front, surround, clfe, side */
4613 0x03, 0x06, 0x05, 0x04
4616 static hda_nid_t alc861_adc_nids[1] = {
4621 static struct hda_input_mux alc861_capture_source = {
4625 { "Front Mic", 0x3 },
4632 /* fill in the dac_nids table from the parsed pin configuration */
4633 static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4638 spec->multiout.dac_nids = spec->private_dac_nids;
4639 for (i = 0; i < cfg->line_outs; i++) {
4640 nid = cfg->line_out_pins[i];
4642 if (i >= ARRAY_SIZE(alc861_dac_nids))
4644 spec->multiout.dac_nids[i] = alc861_dac_nids[i];
4647 spec->multiout.num_dacs = cfg->line_outs;
4651 /* add playback controls from the parsed DAC table */
4652 static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
4653 const struct auto_pin_cfg *cfg)
4656 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
4660 for (i = 0; i < cfg->line_outs; i++) {
4661 nid = spec->multiout.dac_nids[i];
4666 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
4667 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
4669 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
4670 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4673 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
4674 if (nid == alc861_dac_nids[idx])
4676 sprintf(name, "%s Playback Switch", chname[idx]);
4677 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4678 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4685 static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
4693 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
4695 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4696 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4698 spec->multiout.hp_nid = nid;
4703 /* create playback/capture controls for input pins */
4704 static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4706 struct hda_input_mux *imux = &spec->private_imux;
4707 int i, err, idx, idx1;
4709 for (i = 0; i < AUTO_PIN_LAST; i++) {
4710 switch(cfg->input_pins[i]) {
4735 err = new_analog_input(spec, cfg->input_pins[i],
4736 auto_pin_cfg_labels[i], idx, 0x15);
4740 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
4741 imux->items[imux->num_items].index = idx1;
4747 static struct snd_kcontrol_new alc861_capture_mixer[] = {
4748 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4749 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4752 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4753 /* The multiple "Capture Source" controls confuse alsamixer
4754 * So call somewhat different..
4755 *FIXME: the controls appear in the "playback" view!
4757 /* .name = "Capture Source", */
4758 .name = "Input Source",
4760 .info = alc_mux_enum_info,
4761 .get = alc_mux_enum_get,
4762 .put = alc_mux_enum_put,
4767 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
4768 int pin_type, int dac_idx)
4772 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4773 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4777 static void alc861_auto_init_multi_out(struct hda_codec *codec)
4779 struct alc_spec *spec = codec->spec;
4782 for (i = 0; i < spec->autocfg.line_outs; i++) {
4783 hda_nid_t nid = spec->autocfg.line_out_pins[i];
4785 alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
4789 static void alc861_auto_init_hp_out(struct hda_codec *codec)
4791 struct alc_spec *spec = codec->spec;
4794 pin = spec->autocfg.hp_pin;
4795 if (pin) /* connect to front */
4796 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
4799 static void alc861_auto_init_analog_input(struct hda_codec *codec)
4801 struct alc_spec *spec = codec->spec;
4804 for (i = 0; i < AUTO_PIN_LAST; i++) {
4805 hda_nid_t nid = spec->autocfg.input_pins[i];
4806 if ((nid>=0x0c) && (nid <=0x11)) {
4807 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4808 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4813 /* parse the BIOS configuration and set up the alc_spec */
4814 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4815 static int alc861_parse_auto_config(struct hda_codec *codec)
4817 struct alc_spec *spec = codec->spec;
4819 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
4821 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4822 alc861_ignore)) < 0)
4824 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4825 ! spec->autocfg.hp_pin)
4826 return 0; /* can't find valid BIOS pin config */
4828 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
4829 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4830 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
4831 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4834 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4836 if (spec->autocfg.dig_out_pin)
4837 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
4839 if (spec->kctl_alloc)
4840 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4842 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
4844 spec->input_mux = &spec->private_imux;
4846 spec->adc_nids = alc861_adc_nids;
4847 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
4848 spec->mixers[spec->num_mixers] = alc861_capture_mixer;
4854 /* init callback for auto-configuration model -- overriding the default init */
4855 static int alc861_auto_init(struct hda_codec *codec)
4858 alc861_auto_init_multi_out(codec);
4859 alc861_auto_init_hp_out(codec);
4860 alc861_auto_init_analog_input(codec);
4867 * configuration and preset
4869 static struct hda_board_config alc861_cfg_tbl[] = {
4870 { .modelname = "3stack", .config = ALC861_3ST },
4871 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
4872 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
4873 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
4874 { .modelname = "auto", .config = ALC861_AUTO },
4878 static struct alc_config_preset alc861_presets[] = {
4880 .mixers = { alc861_3ST_mixer },
4881 .init_verbs = { alc861_threestack_init_verbs },
4882 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4883 .dac_nids = alc861_dac_nids,
4884 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4885 .channel_mode = alc861_threestack_modes,
4886 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4887 .adc_nids = alc861_adc_nids,
4888 .input_mux = &alc861_capture_source,
4890 [ALC861_3ST_DIG] = {
4891 .mixers = { alc861_base_mixer },
4892 .init_verbs = { alc861_threestack_init_verbs },
4893 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4894 .dac_nids = alc861_dac_nids,
4895 .dig_out_nid = ALC861_DIGOUT_NID,
4896 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4897 .channel_mode = alc861_threestack_modes,
4898 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4899 .adc_nids = alc861_adc_nids,
4900 .input_mux = &alc861_capture_source,
4902 [ALC861_6ST_DIG] = {
4903 .mixers = { alc861_base_mixer },
4904 .init_verbs = { alc861_base_init_verbs },
4905 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4906 .dac_nids = alc861_dac_nids,
4907 .dig_out_nid = ALC861_DIGOUT_NID,
4908 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
4909 .channel_mode = alc861_8ch_modes,
4910 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4911 .adc_nids = alc861_adc_nids,
4912 .input_mux = &alc861_capture_source,
4917 static int patch_alc861(struct hda_codec *codec)
4919 struct alc_spec *spec;
4923 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4929 board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
4930 if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
4931 printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
4932 board_config = ALC861_AUTO;
4935 if (board_config == ALC861_AUTO) {
4936 /* automatic parse from the BIOS config */
4937 err = alc861_parse_auto_config(codec);
4942 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4943 board_config = ALC861_3ST_DIG;
4947 if (board_config != ALC861_AUTO)
4948 setup_preset(spec, &alc861_presets[board_config]);
4950 spec->stream_name_analog = "ALC861 Analog";
4951 spec->stream_analog_playback = &alc861_pcm_analog_playback;
4952 spec->stream_analog_capture = &alc861_pcm_analog_capture;
4954 spec->stream_name_digital = "ALC861 Digital";
4955 spec->stream_digital_playback = &alc861_pcm_digital_playback;
4956 spec->stream_digital_capture = &alc861_pcm_digital_capture;
4958 codec->patch_ops = alc_patch_ops;
4959 if (board_config == ALC861_AUTO)
4960 codec->patch_ops.init = alc861_auto_init;
4968 struct hda_codec_preset snd_hda_preset_realtek[] = {
4969 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
4970 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
4971 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
4972 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4973 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
4974 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
4975 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },