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 * 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 static struct hda_input_mux alc260_test_capture_source = {
2796 { "MIC1 pin", 0x0 },
2797 { "MIC2 pin", 0x1 },
2798 { "LINE1 pin", 0x2 },
2799 { "LINE2 pin", 0x3 },
2801 { "LINE-OUT pin", 0x5 },
2802 { "HP-OUT pin", 0x6 },
2805 static struct snd_kcontrol_new alc260_test_mixer[] = {
2806 /* Output driver widgets */
2807 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2808 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2809 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2810 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
2811 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2812 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
2814 /* Modes for retasking pin widgets */
2815 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
2816 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
2817 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
2818 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
2819 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
2820 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
2822 /* Loopback mixer controls */
2823 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
2824 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
2825 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
2826 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
2827 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
2828 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
2829 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
2830 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
2831 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2832 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2833 HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2834 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2835 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
2836 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
2837 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
2838 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
2841 static struct hda_verb alc260_test_init_verbs[] = {
2842 /* Disable all GPIOs */
2843 {0x01, AC_VERB_SET_GPIO_MASK, 0},
2844 /* Enable retasking pins as output, initially without power amp */
2845 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2846 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2847 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2848 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2849 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2850 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2852 /* Disable digital (SPDIF) pins for now */
2853 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2854 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2856 /* Ensure mic1, mic2, line1 and line2 pin widget take input from the
2857 * OUT1 sum bus when acting as an output.
2859 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
2860 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
2861 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
2862 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
2864 /* Start with output sum widgets muted and their output gains at min */
2865 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2866 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2867 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2868 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2869 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2870 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2871 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2872 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2873 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2875 /* Unmute retasking pin widget output amp left/right (no mixer ctrl) */
2876 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2877 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2878 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2879 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2880 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2881 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2882 /* Also unmute the mono-out pin widget */
2883 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2885 /* Also unmute the retasking pin input amps. Having the input and
2886 * output amps unmuted at the same time doesn't appear to cause any
2889 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2890 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2891 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2892 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2893 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2894 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2896 /* Mute capture amp left and right */
2897 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2898 /* Set ADC connection select to match default mixer setting - line
2901 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2903 /* Do the same for the second ADC: mute capture input amp and
2904 * set ADC connection to line in
2906 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2907 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2909 /* Mute all inputs to mixer widget (even unconnected ones) */
2910 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2911 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2912 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2913 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2914 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2915 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2916 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2917 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2923 static struct hda_pcm_stream alc260_pcm_analog_playback = {
2929 static struct hda_pcm_stream alc260_pcm_analog_capture = {
2935 #define alc260_pcm_digital_playback alc880_pcm_digital_playback
2936 #define alc260_pcm_digital_capture alc880_pcm_digital_capture
2939 * for BIOS auto-configuration
2942 static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
2946 unsigned long vol_val, sw_val;
2950 if (nid >= 0x0f && nid < 0x11) {
2951 nid_vol = nid - 0x7;
2952 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2953 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2954 } else if (nid == 0x11) {
2955 nid_vol = nid - 0x7;
2956 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
2957 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
2958 } else if (nid >= 0x12 && nid <= 0x15) {
2960 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2961 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2965 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
2966 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
2968 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
2969 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
2974 /* add playback controls from the parsed DAC table */
2975 static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
2976 const struct auto_pin_cfg *cfg)
2981 spec->multiout.num_dacs = 1;
2982 spec->multiout.dac_nids = spec->private_dac_nids;
2983 spec->multiout.dac_nids[0] = 0x02;
2985 nid = cfg->line_out_pins[0];
2987 err = alc260_add_playback_controls(spec, nid, "Front");
2992 nid = cfg->speaker_pin;
2994 err = alc260_add_playback_controls(spec, nid, "Speaker");
3001 err = alc260_add_playback_controls(spec, nid, "Headphone");
3008 /* create playback/capture controls for input pins */
3009 static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
3010 const struct auto_pin_cfg *cfg)
3012 struct hda_input_mux *imux = &spec->private_imux;
3015 for (i = 0; i < AUTO_PIN_LAST; i++) {
3016 if (cfg->input_pins[i] >= 0x12) {
3017 idx = cfg->input_pins[i] - 0x12;
3018 err = new_analog_input(spec, cfg->input_pins[i],
3019 auto_pin_cfg_labels[i], idx, 0x07);
3022 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3023 imux->items[imux->num_items].index = idx;
3026 if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
3027 idx = cfg->input_pins[i] - 0x09;
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;
3040 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3041 hda_nid_t nid, int pin_type,
3045 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3046 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3047 /* need the manual connection? */
3049 int idx = nid - 0x12;
3050 snd_hda_codec_write(codec, idx + 0x0b, 0,
3051 AC_VERB_SET_CONNECT_SEL, sel_idx);
3056 static void alc260_auto_init_multi_out(struct hda_codec *codec)
3058 struct alc_spec *spec = codec->spec;
3061 nid = spec->autocfg.line_out_pins[0];
3063 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3065 nid = spec->autocfg.speaker_pin;
3067 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3069 nid = spec->autocfg.hp_pin;
3071 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3074 #define ALC260_PIN_CD_NID 0x16
3075 static void alc260_auto_init_analog_input(struct hda_codec *codec)
3077 struct alc_spec *spec = codec->spec;
3080 for (i = 0; i < AUTO_PIN_LAST; i++) {
3081 hda_nid_t nid = spec->autocfg.input_pins[i];
3083 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3084 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3085 if (nid != ALC260_PIN_CD_NID)
3086 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3093 * generic initialization of ADC, input mixers and output mixers
3095 static struct hda_verb alc260_volume_init_verbs[] = {
3097 * Unmute ADC0-1 and set the default input to mic-in
3099 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
3100 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3101 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
3102 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3104 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3106 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3109 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3110 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3111 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3112 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3113 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3114 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3117 * Set up output mixers (0x08 - 0x0a)
3119 /* set vol=0 to output mixers */
3120 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3121 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3122 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3123 /* set up input amps for analog loopback */
3124 /* Amp Indices: DAC = 0, mixer = 1 */
3125 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3126 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3127 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3128 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3129 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3130 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3135 static int alc260_parse_auto_config(struct hda_codec *codec)
3137 struct alc_spec *spec = codec->spec;
3140 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
3142 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3143 alc260_ignore)) < 0)
3145 if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
3147 if (! spec->kctl_alloc)
3148 return 0; /* can't find valid BIOS pin config */
3149 if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3152 spec->multiout.max_channels = 2;
3154 if (spec->autocfg.dig_out_pin)
3155 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
3156 if (spec->kctl_alloc)
3157 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3159 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
3161 spec->input_mux = &spec->private_imux;
3163 /* check whether NID 0x04 is valid */
3164 wcap = get_wcaps(codec, 0x04);
3165 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3166 if (wcap != AC_WID_AUD_IN) {
3167 spec->adc_nids = alc260_adc_nids_alt;
3168 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
3169 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
3171 spec->adc_nids = alc260_adc_nids;
3172 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
3173 spec->mixers[spec->num_mixers] = alc260_capture_mixer;
3180 /* init callback for auto-configuration model -- overriding the default init */
3181 static int alc260_auto_init(struct hda_codec *codec)
3184 alc260_auto_init_multi_out(codec);
3185 alc260_auto_init_analog_input(codec);
3190 * ALC260 configurations
3192 static struct hda_board_config alc260_cfg_tbl[] = {
3193 { .modelname = "basic", .config = ALC260_BASIC },
3194 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
3195 .config = ALC260_BASIC }, /* Sony VAIO */
3196 { .modelname = "hp", .config = ALC260_HP },
3197 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
3198 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3199 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
3200 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3201 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3202 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
3203 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
3204 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
3205 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
3206 #ifdef CONFIG_SND_DEBUG
3207 { .modelname = "test", .config = ALC260_TEST },
3209 { .modelname = "auto", .config = ALC260_AUTO },
3213 static struct alc_config_preset alc260_presets[] = {
3215 .mixers = { alc260_base_output_mixer,
3217 alc260_pc_beep_mixer,
3218 alc260_capture_mixer },
3219 .init_verbs = { alc260_init_verbs },
3220 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3221 .dac_nids = alc260_dac_nids,
3222 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
3223 .adc_nids = alc260_adc_nids,
3224 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3225 .channel_mode = alc260_modes,
3226 .input_mux = &alc260_capture_source,
3229 .mixers = { alc260_base_output_mixer,
3231 alc260_capture_alt_mixer },
3232 .init_verbs = { alc260_hp_init_verbs },
3233 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3234 .dac_nids = alc260_dac_nids,
3235 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3236 .adc_nids = alc260_hp_adc_nids,
3237 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3238 .channel_mode = alc260_modes,
3239 .input_mux = &alc260_capture_source,
3241 [ALC260_HP_3013] = {
3242 .mixers = { alc260_hp_3013_mixer,
3244 alc260_capture_alt_mixer },
3245 .init_verbs = { alc260_hp_3013_init_verbs },
3246 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3247 .dac_nids = alc260_dac_nids,
3248 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
3249 .adc_nids = alc260_hp_adc_nids,
3250 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3251 .channel_mode = alc260_modes,
3252 .input_mux = &alc260_capture_source,
3254 [ALC260_FUJITSU_S702X] = {
3255 .mixers = { alc260_fujitsu_mixer,
3256 alc260_capture_mixer },
3257 .init_verbs = { alc260_fujitsu_init_verbs },
3258 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3259 .dac_nids = alc260_dac_nids,
3260 .num_adc_nids = ARRAY_SIZE(alc260_fujitsu_adc_nids),
3261 .adc_nids = alc260_fujitsu_adc_nids,
3262 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3263 .channel_mode = alc260_modes,
3264 .input_mux = &alc260_fujitsu_capture_source,
3266 #ifdef CONFIG_SND_DEBUG
3268 .mixers = { alc260_test_mixer,
3269 alc260_capture_mixer },
3270 .init_verbs = { alc260_test_init_verbs },
3271 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
3272 .dac_nids = alc260_test_dac_nids,
3273 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
3274 .adc_nids = alc260_test_adc_nids,
3275 .num_channel_mode = ARRAY_SIZE(alc260_modes),
3276 .channel_mode = alc260_modes,
3277 .input_mux = &alc260_test_capture_source,
3282 static int patch_alc260(struct hda_codec *codec)
3284 struct alc_spec *spec;
3285 int err, board_config;
3287 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3293 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
3294 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
3295 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
3296 board_config = ALC260_AUTO;
3299 if (board_config == ALC260_AUTO) {
3300 /* automatic parse from the BIOS config */
3301 err = alc260_parse_auto_config(codec);
3306 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3307 board_config = ALC260_BASIC;
3311 if (board_config != ALC260_AUTO)
3312 setup_preset(spec, &alc260_presets[board_config]);
3314 spec->stream_name_analog = "ALC260 Analog";
3315 spec->stream_analog_playback = &alc260_pcm_analog_playback;
3316 spec->stream_analog_capture = &alc260_pcm_analog_capture;
3318 spec->stream_name_digital = "ALC260 Digital";
3319 spec->stream_digital_playback = &alc260_pcm_digital_playback;
3320 spec->stream_digital_capture = &alc260_pcm_digital_capture;
3322 codec->patch_ops = alc_patch_ops;
3323 if (board_config == ALC260_AUTO)
3324 codec->patch_ops.init = alc260_auto_init;
3333 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3334 * configuration. Each pin widget can choose any input DACs and a mixer.
3335 * Each ADC is connected from a mixer of all inputs. This makes possible
3336 * 6-channel independent captures.
3338 * In addition, an independent DAC for the multi-playback (not used in this
3341 #define ALC882_DIGOUT_NID 0x06
3342 #define ALC882_DIGIN_NID 0x0a
3344 static struct hda_channel_mode alc882_ch_modes[1] = {
3348 static hda_nid_t alc882_dac_nids[4] = {
3349 /* front, rear, clfe, rear_surr */
3350 0x02, 0x03, 0x04, 0x05
3353 /* identical with ALC880 */
3354 #define alc882_adc_nids alc880_adc_nids
3355 #define alc882_adc_nids_alt alc880_adc_nids_alt
3358 /* FIXME: should be a matrix-type input source selection */
3360 static struct hda_input_mux alc882_capture_source = {
3364 { "Front Mic", 0x1 },
3370 #define alc882_mux_enum_info alc_mux_enum_info
3371 #define alc882_mux_enum_get alc_mux_enum_get
3373 static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3375 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3376 struct alc_spec *spec = codec->spec;
3377 const struct hda_input_mux *imux = spec->input_mux;
3378 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3379 static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
3380 hda_nid_t nid = capture_mixers[adc_idx];
3381 unsigned int *cur_val = &spec->cur_mux[adc_idx];
3382 unsigned int i, idx;
3384 idx = ucontrol->value.enumerated.item[0];
3385 if (idx >= imux->num_items)
3386 idx = imux->num_items - 1;
3387 if (*cur_val == idx && ! codec->in_resume)
3389 for (i = 0; i < imux->num_items; i++) {
3390 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
3391 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3392 v | (imux->items[i].index << 8));
3401 static struct hda_verb alc882_sixstack_ch6_init[] = {
3402 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
3403 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3404 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3405 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3412 static struct hda_verb alc882_sixstack_ch8_init[] = {
3413 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3414 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3415 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3416 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3420 static struct hda_channel_mode alc882_sixstack_modes[2] = {
3421 { 6, alc882_sixstack_ch6_init },
3422 { 8, alc882_sixstack_ch8_init },
3425 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
3426 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
3428 static struct snd_kcontrol_new alc882_base_mixer[] = {
3429 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3430 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3431 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3432 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3433 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3434 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3435 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3436 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3437 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3438 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
3439 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
3440 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3441 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3442 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3443 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3444 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3445 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3446 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3447 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3448 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
3449 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
3450 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3451 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3452 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3453 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3454 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3455 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3458 /* .name = "Capture Source", */
3459 .name = "Input Source",
3461 .info = alc882_mux_enum_info,
3462 .get = alc882_mux_enum_get,
3463 .put = alc882_mux_enum_put,
3468 static struct snd_kcontrol_new alc882_chmode_mixer[] = {
3470 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3471 .name = "Channel Mode",
3472 .info = alc_ch_mode_info,
3473 .get = alc_ch_mode_get,
3474 .put = alc_ch_mode_put,
3479 static struct hda_verb alc882_init_verbs[] = {
3480 /* Front mixer: unmute input/output amp left and right (volume = 0) */
3481 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3482 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3483 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3485 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3486 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3487 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3489 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3490 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3491 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3493 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3494 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3495 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3497 /* Front Pin: output 0 (0x0c) */
3498 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3499 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3500 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3501 /* Rear Pin: output 1 (0x0d) */
3502 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3503 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3504 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3505 /* CLFE Pin: output 2 (0x0e) */
3506 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3507 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3508 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
3509 /* Side Pin: output 3 (0x0f) */
3510 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3511 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3512 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
3513 /* Mic (rear) pin: input vref at 80% */
3514 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3515 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3516 /* Front Mic pin: input vref at 80% */
3517 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3518 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3519 /* Line In pin: input */
3520 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3521 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3522 /* Line-2 In: Headphone output (output 0 - 0x0c) */
3523 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3524 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3525 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3526 /* CD pin widget for input */
3527 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3529 /* FIXME: use matrix-type input source selection */
3530 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3531 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3532 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3533 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3534 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3535 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3537 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3538 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3539 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3540 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3542 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3544 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3545 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3546 /* ADC1: mute amp left and right */
3547 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3548 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3549 /* ADC2: mute amp left and right */
3550 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3551 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3552 /* ADC3: mute amp left and right */
3553 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3554 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3560 * generic initialization of ADC, input mixers and output mixers
3562 static struct hda_verb alc882_auto_init_verbs[] = {
3564 * Unmute ADC0-2 and set the default input to mic-in
3566 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3567 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3568 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3569 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3570 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3571 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3573 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3575 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3578 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3579 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3580 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3581 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3582 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3583 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3586 * Set up output mixers (0x0c - 0x0f)
3588 /* set vol=0 to output mixers */
3589 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3590 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3591 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3592 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3593 /* set up input amps for analog loopback */
3594 /* Amp Indices: DAC = 0, mixer = 1 */
3595 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3596 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3597 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3598 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3599 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3600 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3601 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3602 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3603 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3604 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3606 /* FIXME: use matrix-type input source selection */
3607 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3608 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3609 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3610 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3611 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3612 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3614 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3615 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3616 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3617 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3619 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3620 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3621 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3622 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3627 /* capture mixer elements */
3628 static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
3629 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3630 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3631 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
3632 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
3634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3635 /* The multiple "Capture Source" controls confuse alsamixer
3636 * So call somewhat different..
3637 * FIXME: the controls appear in the "playback" view!
3639 /* .name = "Capture Source", */
3640 .name = "Input Source",
3642 .info = alc882_mux_enum_info,
3643 .get = alc882_mux_enum_get,
3644 .put = alc882_mux_enum_put,
3649 static struct snd_kcontrol_new alc882_capture_mixer[] = {
3650 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3651 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3652 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3653 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3654 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3655 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3658 /* The multiple "Capture Source" controls confuse alsamixer
3659 * So call somewhat different..
3660 * FIXME: the controls appear in the "playback" view!
3662 /* .name = "Capture Source", */
3663 .name = "Input Source",
3665 .info = alc882_mux_enum_info,
3666 .get = alc882_mux_enum_get,
3667 .put = alc882_mux_enum_put,
3672 /* pcm configuration: identiacal with ALC880 */
3673 #define alc882_pcm_analog_playback alc880_pcm_analog_playback
3674 #define alc882_pcm_analog_capture alc880_pcm_analog_capture
3675 #define alc882_pcm_digital_playback alc880_pcm_digital_playback
3676 #define alc882_pcm_digital_capture alc880_pcm_digital_capture
3679 * configuration and preset
3681 static struct hda_board_config alc882_cfg_tbl[] = {
3682 { .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
3683 { .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
3684 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */
3685 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
3686 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
3687 { .modelname = "auto", .config = ALC882_AUTO },
3691 static struct alc_config_preset alc882_presets[] = {
3692 [ALC882_3ST_DIG] = {
3693 .mixers = { alc882_base_mixer },
3694 .init_verbs = { alc882_init_verbs },
3695 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3696 .dac_nids = alc882_dac_nids,
3697 .dig_out_nid = ALC882_DIGOUT_NID,
3698 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3699 .adc_nids = alc882_adc_nids,
3700 .dig_in_nid = ALC882_DIGIN_NID,
3701 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
3702 .channel_mode = alc882_ch_modes,
3703 .input_mux = &alc882_capture_source,
3705 [ALC882_6ST_DIG] = {
3706 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
3707 .init_verbs = { alc882_init_verbs },
3708 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3709 .dac_nids = alc882_dac_nids,
3710 .dig_out_nid = ALC882_DIGOUT_NID,
3711 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3712 .adc_nids = alc882_adc_nids,
3713 .dig_in_nid = ALC882_DIGIN_NID,
3714 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
3715 .channel_mode = alc882_sixstack_modes,
3716 .input_mux = &alc882_capture_source,
3722 * BIOS auto configuration
3724 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
3725 hda_nid_t nid, int pin_type,
3729 struct alc_spec *spec = codec->spec;
3732 if (spec->multiout.dac_nids[dac_idx] == 0x25)
3735 idx = spec->multiout.dac_nids[dac_idx] - 2;
3737 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3738 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3739 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
3743 static void alc882_auto_init_multi_out(struct hda_codec *codec)
3745 struct alc_spec *spec = codec->spec;
3748 for (i = 0; i <= HDA_SIDE; i++) {
3749 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3751 alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3755 static void alc882_auto_init_hp_out(struct hda_codec *codec)
3757 struct alc_spec *spec = codec->spec;
3760 pin = spec->autocfg.hp_pin;
3761 if (pin) /* connect to front */
3762 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
3765 #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
3766 #define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
3768 static void alc882_auto_init_analog_input(struct hda_codec *codec)
3770 struct alc_spec *spec = codec->spec;
3773 for (i = 0; i < AUTO_PIN_LAST; i++) {
3774 hda_nid_t nid = spec->autocfg.input_pins[i];
3775 if (alc882_is_input_pin(nid)) {
3776 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3777 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3778 if (nid != ALC882_PIN_CD_NID)
3779 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3785 /* almost identical with ALC880 parser... */
3786 static int alc882_parse_auto_config(struct hda_codec *codec)
3788 struct alc_spec *spec = codec->spec;
3789 int err = alc880_parse_auto_config(codec);
3794 /* hack - override the init verbs */
3795 spec->init_verbs[0] = alc882_auto_init_verbs;
3799 /* init callback for auto-configuration model -- overriding the default init */
3800 static int alc882_auto_init(struct hda_codec *codec)
3803 alc882_auto_init_multi_out(codec);
3804 alc882_auto_init_hp_out(codec);
3805 alc882_auto_init_analog_input(codec);
3810 * ALC882 Headphone poll in 3.5.1a or 3.5.2
3813 static int patch_alc882(struct hda_codec *codec)
3815 struct alc_spec *spec;
3816 int err, board_config;
3818 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3824 board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
3826 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
3827 printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
3828 board_config = ALC882_AUTO;
3831 if (board_config == ALC882_AUTO) {
3832 /* automatic parse from the BIOS config */
3833 err = alc882_parse_auto_config(codec);
3838 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3839 board_config = ALC882_3ST_DIG;
3843 if (board_config != ALC882_AUTO)
3844 setup_preset(spec, &alc882_presets[board_config]);
3846 spec->stream_name_analog = "ALC882 Analog";
3847 spec->stream_analog_playback = &alc882_pcm_analog_playback;
3848 spec->stream_analog_capture = &alc882_pcm_analog_capture;
3850 spec->stream_name_digital = "ALC882 Digital";
3851 spec->stream_digital_playback = &alc882_pcm_digital_playback;
3852 spec->stream_digital_capture = &alc882_pcm_digital_capture;
3854 if (! spec->adc_nids && spec->input_mux) {
3855 /* check whether NID 0x07 is valid */
3856 unsigned int wcap = get_wcaps(codec, 0x07);
3857 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3858 if (wcap != AC_WID_AUD_IN) {
3859 spec->adc_nids = alc882_adc_nids_alt;
3860 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
3861 spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
3864 spec->adc_nids = alc882_adc_nids;
3865 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
3866 spec->mixers[spec->num_mixers] = alc882_capture_mixer;
3871 codec->patch_ops = alc_patch_ops;
3872 if (board_config == ALC882_AUTO)
3873 codec->patch_ops.init = alc882_auto_init;
3882 #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
3883 #define ALC262_DIGIN_NID ALC880_DIGIN_NID
3885 #define alc262_dac_nids alc260_dac_nids
3886 #define alc262_adc_nids alc882_adc_nids
3887 #define alc262_adc_nids_alt alc882_adc_nids_alt
3889 #define alc262_modes alc260_modes
3890 #define alc262_capture_source alc882_capture_source
3892 static struct snd_kcontrol_new alc262_base_mixer[] = {
3893 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3894 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3895 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3896 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3897 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3898 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3899 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3900 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3901 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3902 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
3903 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3904 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3905 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
3906 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3907 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3908 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
3909 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3910 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3912 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3913 .name = "Capture Source",
3915 .info = alc882_mux_enum_info,
3916 .get = alc882_mux_enum_get,
3917 .put = alc882_mux_enum_put,
3922 #define alc262_capture_mixer alc882_capture_mixer
3923 #define alc262_capture_alt_mixer alc882_capture_alt_mixer
3926 * generic initialization of ADC, input mixers and output mixers
3928 static struct hda_verb alc262_init_verbs[] = {
3930 * Unmute ADC0-2 and set the default input to mic-in
3932 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3933 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3934 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3935 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3936 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3937 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3939 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3941 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3944 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3945 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3946 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3947 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3948 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3949 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3952 * Set up output mixers (0x0c - 0x0e)
3954 /* set vol=0 to output mixers */
3955 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3956 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3957 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3958 /* set up input amps for analog loopback */
3959 /* Amp Indices: DAC = 0, mixer = 1 */
3960 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3961 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3962 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3963 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3964 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3965 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3967 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3968 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3969 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3970 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3971 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3972 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3974 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3975 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3976 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3977 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3978 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3980 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3981 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3983 /* FIXME: use matrix-type input source selection */
3984 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3985 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3986 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3987 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3988 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3989 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3991 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3992 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3993 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3994 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3996 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3997 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3998 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3999 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4004 /* add playback controls from the parsed DAC table */
4005 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4010 spec->multiout.num_dacs = 1; /* only use one dac */
4011 spec->multiout.dac_nids = spec->private_dac_nids;
4012 spec->multiout.dac_nids[0] = 2;
4014 nid = cfg->line_out_pins[0];
4016 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
4017 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4019 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
4020 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4024 nid = cfg->speaker_pin;
4027 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4028 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4030 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4031 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4034 if (! cfg->line_out_pins[0])
4035 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
4036 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4038 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
4039 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4045 /* spec->multiout.hp_nid = 2; */
4047 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4048 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
4050 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4051 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4054 if (! cfg->line_out_pins[0])
4055 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
4056 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
4058 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4059 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4066 /* identical with ALC880 */
4067 #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
4070 * generic initialization of ADC, input mixers and output mixers
4072 static struct hda_verb alc262_volume_init_verbs[] = {
4074 * Unmute ADC0-2 and set the default input to mic-in
4076 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4077 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4078 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4079 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4080 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4081 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4083 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4085 * Note: PASD motherboards uses the Line In 2 as the input for front panel
4088 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
4089 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4090 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4091 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4092 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4093 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
4096 * Set up output mixers (0x0c - 0x0f)
4098 /* set vol=0 to output mixers */
4099 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4100 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4101 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4103 /* set up input amps for analog loopback */
4104 /* Amp Indices: DAC = 0, mixer = 1 */
4105 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4106 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4107 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4108 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4109 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4110 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4112 /* FIXME: use matrix-type input source selection */
4113 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4114 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4115 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4116 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4117 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4118 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4120 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4121 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4122 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4123 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4125 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
4126 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
4127 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
4128 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
4133 /* pcm configuration: identiacal with ALC880 */
4134 #define alc262_pcm_analog_playback alc880_pcm_analog_playback
4135 #define alc262_pcm_analog_capture alc880_pcm_analog_capture
4136 #define alc262_pcm_digital_playback alc880_pcm_digital_playback
4137 #define alc262_pcm_digital_capture alc880_pcm_digital_capture
4140 * BIOS auto configuration
4142 static int alc262_parse_auto_config(struct hda_codec *codec)
4144 struct alc_spec *spec = codec->spec;
4146 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
4148 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4149 alc262_ignore)) < 0)
4151 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4152 ! spec->autocfg.hp_pin)
4153 return 0; /* can't find valid BIOS pin config */
4154 if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4155 (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4158 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4160 if (spec->autocfg.dig_out_pin)
4161 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
4162 if (spec->autocfg.dig_in_pin)
4163 spec->dig_in_nid = ALC262_DIGIN_NID;
4165 if (spec->kctl_alloc)
4166 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4168 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
4169 spec->input_mux = &spec->private_imux;
4174 #define alc262_auto_init_multi_out alc882_auto_init_multi_out
4175 #define alc262_auto_init_hp_out alc882_auto_init_hp_out
4176 #define alc262_auto_init_analog_input alc882_auto_init_analog_input
4179 /* init callback for auto-configuration model -- overriding the default init */
4180 static int alc262_auto_init(struct hda_codec *codec)
4183 alc262_auto_init_multi_out(codec);
4184 alc262_auto_init_hp_out(codec);
4185 alc262_auto_init_analog_input(codec);
4190 * configuration and preset
4192 static struct hda_board_config alc262_cfg_tbl[] = {
4193 { .modelname = "basic", .config = ALC262_BASIC },
4194 { .modelname = "auto", .config = ALC262_AUTO },
4198 static struct alc_config_preset alc262_presets[] = {
4200 .mixers = { alc262_base_mixer },
4201 .init_verbs = { alc262_init_verbs },
4202 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
4203 .dac_nids = alc262_dac_nids,
4205 .num_channel_mode = ARRAY_SIZE(alc262_modes),
4206 .channel_mode = alc262_modes,
4207 .input_mux = &alc262_capture_source,
4211 static int patch_alc262(struct hda_codec *codec)
4213 struct alc_spec *spec;
4217 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4223 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
4226 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4227 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4228 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4229 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4233 board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
4234 if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
4235 printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
4236 board_config = ALC262_AUTO;
4239 if (board_config == ALC262_AUTO) {
4240 /* automatic parse from the BIOS config */
4241 err = alc262_parse_auto_config(codec);
4246 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4247 board_config = ALC262_BASIC;
4251 if (board_config != ALC262_AUTO)
4252 setup_preset(spec, &alc262_presets[board_config]);
4254 spec->stream_name_analog = "ALC262 Analog";
4255 spec->stream_analog_playback = &alc262_pcm_analog_playback;
4256 spec->stream_analog_capture = &alc262_pcm_analog_capture;
4258 spec->stream_name_digital = "ALC262 Digital";
4259 spec->stream_digital_playback = &alc262_pcm_digital_playback;
4260 spec->stream_digital_capture = &alc262_pcm_digital_capture;
4262 if (! spec->adc_nids && spec->input_mux) {
4263 /* check whether NID 0x07 is valid */
4264 unsigned int wcap = get_wcaps(codec, 0x07);
4266 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
4267 if (wcap != AC_WID_AUD_IN) {
4268 spec->adc_nids = alc262_adc_nids_alt;
4269 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
4270 spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
4273 spec->adc_nids = alc262_adc_nids;
4274 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
4275 spec->mixers[spec->num_mixers] = alc262_capture_mixer;
4280 codec->patch_ops = alc_patch_ops;
4281 if (board_config == ALC262_AUTO)
4282 codec->patch_ops.init = alc262_auto_init;
4289 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4293 * set the path ways for 2 channel output
4294 * need to set the codec line out and mic 1 pin widgets to inputs
4296 static struct hda_verb alc861_threestack_ch2_init[] = {
4297 /* set pin widget 1Ah (line in) for input */
4298 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4299 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4300 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4302 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
4303 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
4304 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
4309 * need to set the codec line out and mic 1 pin widgets to outputs
4311 static struct hda_verb alc861_threestack_ch6_init[] = {
4312 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4313 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4314 /* set pin widget 18h (mic1) for output (CLFE)*/
4315 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4317 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
4318 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
4320 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
4321 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
4322 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
4326 static struct hda_channel_mode alc861_threestack_modes[2] = {
4327 { 2, alc861_threestack_ch2_init },
4328 { 6, alc861_threestack_ch6_init },
4333 static struct snd_kcontrol_new alc861_base_mixer[] = {
4334 /* output mixer control */
4335 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4336 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4337 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4338 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4339 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
4341 /*Input mixer control */
4342 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4343 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4344 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4345 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4346 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4347 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4348 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4349 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4350 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4351 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4353 /* Capture mixer control */
4354 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4355 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4358 .name = "Capture Source",
4360 .info = alc_mux_enum_info,
4361 .get = alc_mux_enum_get,
4362 .put = alc_mux_enum_put,
4367 static struct snd_kcontrol_new alc861_3ST_mixer[] = {
4368 /* output mixer control */
4369 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4370 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4371 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4372 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4373 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4375 /* Input mixer control */
4376 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4377 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4378 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4379 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4380 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4381 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4382 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4383 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4384 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4385 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4387 /* Capture mixer control */
4388 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4389 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4392 .name = "Capture Source",
4394 .info = alc_mux_enum_info,
4395 .get = alc_mux_enum_get,
4396 .put = alc_mux_enum_put,
4399 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4400 .name = "Channel Mode",
4401 .info = alc_ch_mode_info,
4402 .get = alc_ch_mode_get,
4403 .put = alc_ch_mode_put,
4404 .private_value = ARRAY_SIZE(alc861_threestack_modes),
4410 * generic initialization of ADC, input mixers and output mixers
4412 static struct hda_verb alc861_base_init_verbs[] = {
4414 * Unmute ADC0 and set the default input to mic-in
4416 /* port-A for surround (rear panel) */
4417 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4418 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
4419 /* port-B for mic-in (rear panel) with vref */
4420 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4421 /* port-C for line-in (rear panel) */
4422 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4423 /* port-D for Front */
4424 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4425 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4426 /* port-E for HP out (front panel) */
4427 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4428 /* route front PCM to HP */
4429 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4430 /* port-F for mic-in (front panel) with vref */
4431 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4432 /* port-G for CLFE (rear panel) */
4433 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4434 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
4435 /* port-H for side (rear panel) */
4436 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4437 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
4439 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4440 /* route front mic to ADC1*/
4441 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4442 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4444 /* Unmute DAC0~3 & spdif out*/
4445 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4446 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4447 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4448 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4449 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4451 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4452 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4453 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4454 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4455 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4457 /* Unmute Stereo Mixer 15 */
4458 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4459 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4460 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4461 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4463 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4464 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4465 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4466 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4467 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4468 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4469 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4470 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4471 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4472 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4477 static struct hda_verb alc861_threestack_init_verbs[] = {
4479 * Unmute ADC0 and set the default input to mic-in
4481 /* port-A for surround (rear panel) */
4482 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4483 /* port-B for mic-in (rear panel) with vref */
4484 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4485 /* port-C for line-in (rear panel) */
4486 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4487 /* port-D for Front */
4488 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4489 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4490 /* port-E for HP out (front panel) */
4491 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4492 /* route front PCM to HP */
4493 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4494 /* port-F for mic-in (front panel) with vref */
4495 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4496 /* port-G for CLFE (rear panel) */
4497 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4498 /* port-H for side (rear panel) */
4499 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4501 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4502 /* route front mic to ADC1*/
4503 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4504 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4505 /* Unmute DAC0~3 & spdif out*/
4506 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4507 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4508 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4509 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4510 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4512 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4513 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4514 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4515 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4516 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4518 /* Unmute Stereo Mixer 15 */
4519 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4520 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4521 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4522 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4524 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4525 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4526 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4527 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4528 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4529 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4530 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4531 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4532 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4533 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4537 * generic initialization of ADC, input mixers and output mixers
4539 static struct hda_verb alc861_auto_init_verbs[] = {
4541 * Unmute ADC0 and set the default input to mic-in
4543 // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4544 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4546 /* Unmute DAC0~3 & spdif out*/
4547 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4548 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4549 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4550 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4551 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4553 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4554 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4555 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4556 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4557 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4559 /* Unmute Stereo Mixer 15 */
4560 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4561 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4562 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4563 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
4565 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4566 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4567 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4568 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4569 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4570 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4571 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4572 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4574 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4575 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4576 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4577 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4578 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4579 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4580 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4581 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4583 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1
4588 /* pcm configuration: identiacal with ALC880 */
4589 #define alc861_pcm_analog_playback alc880_pcm_analog_playback
4590 #define alc861_pcm_analog_capture alc880_pcm_analog_capture
4591 #define alc861_pcm_digital_playback alc880_pcm_digital_playback
4592 #define alc861_pcm_digital_capture alc880_pcm_digital_capture
4595 #define ALC861_DIGOUT_NID 0x07
4597 static struct hda_channel_mode alc861_8ch_modes[1] = {
4601 static hda_nid_t alc861_dac_nids[4] = {
4602 /* front, surround, clfe, side */
4603 0x03, 0x06, 0x05, 0x04
4606 static hda_nid_t alc861_adc_nids[1] = {
4611 static struct hda_input_mux alc861_capture_source = {
4615 { "Front Mic", 0x3 },
4622 /* fill in the dac_nids table from the parsed pin configuration */
4623 static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4628 spec->multiout.dac_nids = spec->private_dac_nids;
4629 for (i = 0; i < cfg->line_outs; i++) {
4630 nid = cfg->line_out_pins[i];
4632 if (i >= ARRAY_SIZE(alc861_dac_nids))
4634 spec->multiout.dac_nids[i] = alc861_dac_nids[i];
4637 spec->multiout.num_dacs = cfg->line_outs;
4641 /* add playback controls from the parsed DAC table */
4642 static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
4643 const struct auto_pin_cfg *cfg)
4646 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
4650 for (i = 0; i < cfg->line_outs; i++) {
4651 nid = spec->multiout.dac_nids[i];
4656 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
4657 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
4659 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
4660 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4663 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
4664 if (nid == alc861_dac_nids[idx])
4666 sprintf(name, "%s Playback Switch", chname[idx]);
4667 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4668 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4675 static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
4683 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
4685 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4686 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4688 spec->multiout.hp_nid = nid;
4693 /* create playback/capture controls for input pins */
4694 static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4696 struct hda_input_mux *imux = &spec->private_imux;
4697 int i, err, idx, idx1;
4699 for (i = 0; i < AUTO_PIN_LAST; i++) {
4700 switch(cfg->input_pins[i]) {
4725 err = new_analog_input(spec, cfg->input_pins[i],
4726 auto_pin_cfg_labels[i], idx, 0x15);
4730 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
4731 imux->items[imux->num_items].index = idx1;
4737 static struct snd_kcontrol_new alc861_capture_mixer[] = {
4738 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4739 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4743 /* The multiple "Capture Source" controls confuse alsamixer
4744 * So call somewhat different..
4745 *FIXME: the controls appear in the "playback" view!
4747 /* .name = "Capture Source", */
4748 .name = "Input Source",
4750 .info = alc_mux_enum_info,
4751 .get = alc_mux_enum_get,
4752 .put = alc_mux_enum_put,
4757 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
4758 int pin_type, int dac_idx)
4762 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4763 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4767 static void alc861_auto_init_multi_out(struct hda_codec *codec)
4769 struct alc_spec *spec = codec->spec;
4772 for (i = 0; i < spec->autocfg.line_outs; i++) {
4773 hda_nid_t nid = spec->autocfg.line_out_pins[i];
4775 alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
4779 static void alc861_auto_init_hp_out(struct hda_codec *codec)
4781 struct alc_spec *spec = codec->spec;
4784 pin = spec->autocfg.hp_pin;
4785 if (pin) /* connect to front */
4786 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
4789 static void alc861_auto_init_analog_input(struct hda_codec *codec)
4791 struct alc_spec *spec = codec->spec;
4794 for (i = 0; i < AUTO_PIN_LAST; i++) {
4795 hda_nid_t nid = spec->autocfg.input_pins[i];
4796 if ((nid>=0x0c) && (nid <=0x11)) {
4797 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4798 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4803 /* parse the BIOS configuration and set up the alc_spec */
4804 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4805 static int alc861_parse_auto_config(struct hda_codec *codec)
4807 struct alc_spec *spec = codec->spec;
4809 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
4811 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4812 alc861_ignore)) < 0)
4814 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4815 ! spec->autocfg.hp_pin)
4816 return 0; /* can't find valid BIOS pin config */
4818 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
4819 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4820 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
4821 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4824 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4826 if (spec->autocfg.dig_out_pin)
4827 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
4829 if (spec->kctl_alloc)
4830 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4832 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
4834 spec->input_mux = &spec->private_imux;
4836 spec->adc_nids = alc861_adc_nids;
4837 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
4838 spec->mixers[spec->num_mixers] = alc861_capture_mixer;
4844 /* init callback for auto-configuration model -- overriding the default init */
4845 static int alc861_auto_init(struct hda_codec *codec)
4848 alc861_auto_init_multi_out(codec);
4849 alc861_auto_init_hp_out(codec);
4850 alc861_auto_init_analog_input(codec);
4857 * configuration and preset
4859 static struct hda_board_config alc861_cfg_tbl[] = {
4860 { .modelname = "3stack", .config = ALC861_3ST },
4861 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
4862 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
4863 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
4864 { .modelname = "auto", .config = ALC861_AUTO },
4868 static struct alc_config_preset alc861_presets[] = {
4870 .mixers = { alc861_3ST_mixer },
4871 .init_verbs = { alc861_threestack_init_verbs },
4872 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4873 .dac_nids = alc861_dac_nids,
4874 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4875 .channel_mode = alc861_threestack_modes,
4876 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4877 .adc_nids = alc861_adc_nids,
4878 .input_mux = &alc861_capture_source,
4880 [ALC861_3ST_DIG] = {
4881 .mixers = { alc861_base_mixer },
4882 .init_verbs = { alc861_threestack_init_verbs },
4883 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4884 .dac_nids = alc861_dac_nids,
4885 .dig_out_nid = ALC861_DIGOUT_NID,
4886 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4887 .channel_mode = alc861_threestack_modes,
4888 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4889 .adc_nids = alc861_adc_nids,
4890 .input_mux = &alc861_capture_source,
4892 [ALC861_6ST_DIG] = {
4893 .mixers = { alc861_base_mixer },
4894 .init_verbs = { alc861_base_init_verbs },
4895 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4896 .dac_nids = alc861_dac_nids,
4897 .dig_out_nid = ALC861_DIGOUT_NID,
4898 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
4899 .channel_mode = alc861_8ch_modes,
4900 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4901 .adc_nids = alc861_adc_nids,
4902 .input_mux = &alc861_capture_source,
4907 static int patch_alc861(struct hda_codec *codec)
4909 struct alc_spec *spec;
4913 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4919 board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
4920 if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
4921 printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
4922 board_config = ALC861_AUTO;
4925 if (board_config == ALC861_AUTO) {
4926 /* automatic parse from the BIOS config */
4927 err = alc861_parse_auto_config(codec);
4932 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4933 board_config = ALC861_3ST_DIG;
4937 if (board_config != ALC861_AUTO)
4938 setup_preset(spec, &alc861_presets[board_config]);
4940 spec->stream_name_analog = "ALC861 Analog";
4941 spec->stream_analog_playback = &alc861_pcm_analog_playback;
4942 spec->stream_analog_capture = &alc861_pcm_analog_capture;
4944 spec->stream_name_digital = "ALC861 Digital";
4945 spec->stream_digital_playback = &alc861_pcm_digital_playback;
4946 spec->stream_digital_capture = &alc861_pcm_digital_capture;
4948 codec->patch_ops = alc_patch_ops;
4949 if (board_config == ALC861_AUTO)
4950 codec->patch_ops.init = alc861_auto_init;
4958 struct hda_codec_preset snd_hda_preset_realtek[] = {
4959 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
4960 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
4961 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
4962 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4963 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
4964 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
4965 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },