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